Remove unneeded modest_osso_load_state() and modest_osso_save_state()
[modest] / src / hildon2 / modest-main-window.c
1 /* Copyright (c) 2006, 2008 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-text-utils.h"
65 #include "modest-signal-mgr.h"
66 #include <tny-gtk-folder-store-tree-model.h>
67 #include <modest-accounts-window.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_("ckdg_fi_new_folder_name"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
265         { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_rename_folder"), 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_delete_messages"), 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_delete_messages"),      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 row activated */
903         priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "row-activated",
904                                                        G_CALLBACK(on_folder_view_row_activated),
905                                                        self);
906
907         /* header view */
908         priv->sighandlers = 
909                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
910                                            G_CALLBACK(modest_ui_actions_on_header_selected), self);
911         priv->sighandlers = 
912                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
913                                            G_CALLBACK(modest_ui_actions_on_header_activated), self);
914         priv->sighandlers = 
915                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
916                                            G_CALLBACK(modest_ui_actions_on_item_not_found), self);
917         priv->sighandlers = 
918                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
919                                            G_CALLBACK(on_inner_widgets_key_pressed), self);
920         priv->sighandlers = 
921                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
922                                            G_CALLBACK(on_msg_count_changed), self);
923         priv->sighandlers = 
924                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
925                                            G_CALLBACK (on_header_view_focus_in), self);
926         priv->sighandlers = 
927                 modest_signal_mgr_connect (priv->sighandlers,
928                                            G_OBJECT (priv->header_view), 
929                                            "updating-msg-list",
930                                            G_CALLBACK (on_updating_msg_list), 
931                                            self);
932         
933         /* window */
934         /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
935          * in destroy stage */
936         g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
937
938         g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
939
940         /* Mail Operation Queue */
941         priv->sighandlers = 
942                 modest_signal_mgr_connect (priv->sighandlers,
943                                            G_OBJECT (modest_runtime_get_mail_operation_queue ()),
944                                            "queue-changed", 
945                                            G_CALLBACK (on_queue_changed), self);
946         
947         /* Track changes in the device name */
948         priv->sighandlers = 
949                 modest_signal_mgr_connect (priv->sighandlers,
950                                            G_OBJECT(modest_runtime_get_conf ()),
951                                            "key_changed", 
952                                            G_CALLBACK (on_configuration_key_changed), 
953                                            self);
954         
955         /* Track account changes. We need to refresh the toolbar */
956         priv->sighandlers = 
957                 modest_signal_mgr_connect (priv->sighandlers,
958                                            G_OBJECT (modest_runtime_get_account_store ()),
959                                            "account_inserted", 
960                                            G_CALLBACK (on_account_inserted),
961                                            self);
962         priv->sighandlers = 
963                 modest_signal_mgr_connect (priv->sighandlers,
964                                            G_OBJECT (modest_runtime_get_account_store ()),
965                                            "account_removed", 
966                                            G_CALLBACK (on_account_removed),
967                                            self);
968
969         /* We need to refresh the send & receive menu to change the bold
970          * account when the default account changes. */
971         priv->sighandlers = 
972                 modest_signal_mgr_connect (priv->sighandlers,
973                                            G_OBJECT (modest_runtime_get_account_mgr ()),
974                                            "default_account_changed", 
975                                            G_CALLBACK (on_default_account_changed),
976                                            self);
977
978         /* Account store */
979         priv->sighandlers = 
980                 modest_signal_mgr_connect (priv->sighandlers,
981                                            G_OBJECT (modest_runtime_get_account_store ()),
982                                            "account_changed", 
983                                            G_CALLBACK (on_account_changed),
984                                            self);
985 }
986
987 static void 
988 on_hildon_program_is_topmost_notify(GObject *self,
989                                     GParamSpec *propert_param, 
990                                     gpointer user_data)
991 {
992         HildonProgram *app = HILDON_PROGRAM (self);
993         
994         /* Note that use of hildon_program_set_can_hibernate() 
995          * is generally referred to as "setting the killable flag", 
996          * though hibernation does not seem equal to death.
997          * murrayc */
998                  
999         if (hildon_program_get_is_topmost (app)) {
1000                 /* Prevent hibernation when the progam comes to the foreground,
1001                  * because hibernation should only happen when the application 
1002                  * is in the background: */
1003                 hildon_program_set_can_hibernate (app, FALSE);
1004
1005                 /* Remove new mail visual notifications */
1006                 modest_platform_remove_new_mail_notifications (TRUE);
1007         } else {
1008                 /* Allow hibernation if the program has gone to the background: */
1009                 
1010                 /* However, prevent hibernation while the settings are being changed: */
1011                 const gboolean hibernation_prevented = 
1012                         modest_window_mgr_get_hibernation_is_prevented (
1013                                                                         modest_runtime_get_window_mgr ()); 
1014         
1015                 if (hibernation_prevented)
1016                         hildon_program_set_can_hibernate (app, FALSE);
1017                 else {
1018                         /* Allow hibernation, after saving the state: */
1019                         hildon_program_set_can_hibernate (app, TRUE);
1020                 }
1021         }       
1022 }
1023
1024 typedef struct
1025 {
1026         gulong handler_id;
1027 } ShowHelper;
1028
1029 static void
1030 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1031 {
1032         ShowHelper *helper = (ShowHelper *) user_data;
1033         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1034
1035         priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1036         modest_main_window_set_contents_style (MODEST_MAIN_WINDOW (self), 
1037                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_FOLDERS);
1038         gtk_tree_view_expand_all (GTK_TREE_VIEW (priv->folder_view));
1039
1040         gtk_widget_show (GTK_WIDGET (priv->folder_view));
1041
1042         /* Connect signals */
1043         connect_signals (MODEST_MAIN_WINDOW (self));
1044
1045         /* Set account store */
1046         tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1047                                                   TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1048
1049         /* Restore window & widget settings */
1050         priv->wait_for_settings = TRUE;
1051         restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1052         priv->wait_for_settings = FALSE;
1053
1054         /* Check if accounts exist and show the account wizard if not */
1055         gboolean accounts_exist =
1056                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1057
1058         if (!accounts_exist) {
1059                 /* This is necessary to have the main window shown behind the dialog
1060                 It's an ugly hack... jschmid */
1061                 gtk_widget_show_all(GTK_WIDGET(self));
1062                 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1063         } else {
1064                 update_menus (MODEST_MAIN_WINDOW (self));
1065         }
1066
1067         /* Never call this function again (NOTE that it could happen
1068            as we hide the main window instead of closing it while
1069            there are operations ongoing) and free the helper */
1070         g_signal_handler_disconnect (self, helper->handler_id);
1071         g_slice_free (ShowHelper, helper);
1072 }
1073
1074 static void 
1075 osso_display_event_cb (osso_display_state_t state, 
1076                        gpointer data)
1077 {
1078         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1079
1080         priv->display_state = state;
1081
1082         /* Stop blinking if the screen becomes on */
1083         if (priv->display_state == OSSO_DISPLAY_ON)
1084                 modest_platform_remove_new_mail_notifications (TRUE);
1085 }
1086
1087 ModestWindow *
1088 modest_main_window_new (void)
1089 {
1090         ModestMainWindow *self = NULL;  
1091         ModestMainWindowPrivate *priv = NULL;
1092         ModestWindowPrivate *parent_priv = NULL;
1093         ModestDimmingRulesGroup *menu_rules_group = NULL;
1094         ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1095         GtkActionGroup *action_group = NULL;
1096         GError *error = NULL;
1097         HildonProgram *app;
1098         GdkPixbuf *window_icon;
1099         ShowHelper *helper;
1100         
1101         self  = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1102         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1103         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1104
1105         parent_priv->ui_manager = gtk_ui_manager_new();
1106         parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1107
1108         action_group = gtk_action_group_new ("ModestMainWindowActions");
1109         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1110
1111         menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1112         toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1113
1114         /* Add common actions */
1115         gtk_action_group_add_actions (action_group,
1116                                       modest_action_entries,
1117                                       G_N_ELEMENTS (modest_action_entries),
1118                                       self);
1119
1120         gtk_action_group_add_actions (action_group,
1121                                       modest_folder_view_action_entries,
1122                                       G_N_ELEMENTS (modest_folder_view_action_entries),
1123                                       self);
1124
1125         gtk_action_group_add_actions (action_group,
1126                                       modest_header_view_action_entries,
1127                                       G_N_ELEMENTS (modest_header_view_action_entries),
1128                                       self);
1129
1130         gtk_action_group_add_toggle_actions (action_group,
1131                                              modest_main_window_toggle_action_entries,
1132                                              G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1133                                              self);
1134
1135         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1136         g_object_unref (action_group);
1137
1138         /* Load the UI definition */
1139         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1140                                          MODEST_UIDIR "modest-main-window-ui.xml", &error);
1141         if (error != NULL) {
1142                 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1143                 g_error_free (error);
1144                 error = NULL;
1145         }
1146
1147         /* Add common dimming rules */
1148         modest_dimming_rules_group_add_rules (menu_rules_group, 
1149                                               modest_main_window_menu_dimming_entries,
1150                                               G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1151                                               MODEST_WINDOW (self));
1152         modest_dimming_rules_group_add_rules (toolbar_rules_group, 
1153                                               modest_main_window_toolbar_dimming_entries,
1154                                               G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1155                                               MODEST_WINDOW (self));
1156
1157         /* Insert dimming rules group for this window */
1158         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1159         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1160         g_object_unref (menu_rules_group);
1161         g_object_unref (toolbar_rules_group);
1162         
1163         /* Add accelerators */
1164         gtk_window_add_accel_group (GTK_WINDOW (self), 
1165                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1166
1167         /* Menubar. Update the state of some toggles */
1168         parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1169         hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1170         gtk_widget_show (parent_priv->menubar);
1171
1172         /* Get device name */
1173         modest_maemo_utils_get_device_name ();
1174
1175         /* header view */
1176         priv->header_view =
1177                 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1178         g_object_ref (priv->header_view);
1179         if (!priv->header_view)
1180                 g_printerr ("modest: cannot instantiate header view\n");
1181         modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1182         modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1183                                       MODEST_CONF_HEADER_VIEW_KEY);
1184
1185         /* Other style properties of header view */
1186         g_object_set (G_OBJECT (priv->header_view), 
1187                       "rules-hint", FALSE,
1188                       NULL);
1189         /* gtk_widget_show (priv->header_view); */
1190
1191         /* Empty view */ 
1192         priv->empty_view = create_empty_view ();
1193         gtk_widget_show (priv->empty_view);
1194         g_object_ref (priv->empty_view);
1195                  
1196         /* Create scrolled windows */
1197         priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1198         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1199                                         GTK_POLICY_NEVER,
1200                                         GTK_POLICY_AUTOMATIC);
1201         /* gtk_widget_show (priv->contents_widget); */
1202
1203         /* putting it all together... */
1204         priv->main_vbox = gtk_vbox_new (FALSE, 6);
1205         gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->contents_widget, TRUE, TRUE,0);
1206         gtk_widget_show (priv->main_vbox);
1207         
1208         gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1209         
1210         app = hildon_program_get_instance ();
1211         hildon_program_add_window (app, HILDON_WINDOW (self));
1212         
1213         g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1214                 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1215
1216         /* Connect to "show" action. We delay the creation of some
1217            elements until that moment */
1218         helper = g_slice_new0 (ShowHelper);
1219         helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1220                                                G_CALLBACK (modest_main_window_on_show), 
1221                                                helper);
1222         
1223         /* Set window icon */
1224         window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1225         if (window_icon) {
1226                 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1227                 g_object_unref (window_icon);
1228         }
1229
1230         /* Listen for changes in the screen, we don't want to show a
1231            led pattern when the display is on for example */
1232         osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1233                                       osso_display_event_cb,
1234                                       self); 
1235
1236         /* Dont't restore settings here, 
1237          * because it requires a gtk_widget_show(), 
1238          * and we don't want to do that until later,
1239          * so that the UI is not visible for non-menu D-Bus activation.
1240          */
1241
1242         return MODEST_WINDOW(self);
1243 }
1244
1245 void 
1246 modest_main_window_set_style (ModestMainWindow *self, 
1247                               ModestMainWindowStyle style)
1248 {
1249         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1250
1251         /* We only provide simple style */
1252         return;
1253 }
1254
1255 ModestMainWindowStyle
1256 modest_main_window_get_style (ModestMainWindow *self)
1257 {
1258         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1259
1260         return MODEST_MAIN_WINDOW_STYLE_SIMPLE;
1261 }
1262
1263 static void
1264 toolbar_resize (ModestMainWindow *self)
1265 {
1266         ModestMainWindowPrivate *priv = NULL;
1267         ModestWindowPrivate *parent_priv = NULL;
1268         GtkWidget *widget;
1269         gint static_button_size;
1270         ModestWindowMgr *mgr;
1271
1272         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1273         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1274         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1275
1276         mgr = modest_runtime_get_window_mgr ();
1277         static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1278
1279         if (parent_priv->toolbar) {
1280                 /* left size buttons */
1281                 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1282                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1283                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1284                 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1285                 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1286                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1287                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1288                 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1289                 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1290                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1291                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1292                 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1293                 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
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                 
1298                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1299                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1300                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1301                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1302                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1303                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1304                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1305                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1306         }
1307                 
1308 }
1309
1310 static void 
1311 modest_main_window_show_toolbar (ModestWindow *self,
1312                                  gboolean show_toolbar)
1313 {
1314         ModestMainWindowPrivate *priv = NULL;
1315         ModestWindowPrivate *parent_priv = NULL;        
1316         GtkWidget *reply_button = NULL, *menu = NULL;
1317         GtkWidget *placeholder = NULL;
1318         gint insert_index;
1319
1320         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1321         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1322         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1323
1324         /* Set optimized view status */
1325         priv->optimized_view = !show_toolbar;
1326
1327         if (!parent_priv->toolbar) {
1328                 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
1329                                                                   "/ToolBar");
1330                 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1331
1332                 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1333                 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1334                 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1335                 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1336                 toolbar_resize (MODEST_MAIN_WINDOW (self));
1337                 
1338                 /* Add ProgressBar (Transfer toolbar) */ 
1339                 priv->progress_bar = modest_progress_bar_new ();
1340                 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1341                 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1342                 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1343                 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1344                 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1345                 
1346                 /* Connect cancel 'clicked' signal to abort progress mode */
1347                 g_signal_connect(priv->cancel_toolitem, "clicked",
1348                                  G_CALLBACK(cancel_progressbar),
1349                                  self);
1350                 
1351                 /* Add it to the observers list */
1352                 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1353
1354                 /* Add to window */
1355                 hildon_window_add_toolbar (HILDON_WINDOW (self), 
1356                                            GTK_TOOLBAR (parent_priv->toolbar));
1357
1358                 /* Set reply button tap and hold menu */
1359                 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
1360                                                           "/ToolBar/ToolbarMessageReply");
1361                 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1362                                                   "/ToolbarReplyCSM");
1363                 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1364
1365                 /* Set send & receive button tap and hold menu */
1366                 update_menus (MODEST_MAIN_WINDOW (self));
1367         }
1368         
1369         if (show_toolbar) {
1370                 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */ 
1371                 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1372                 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1373
1374                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1375                 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1376                         set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1377                 else
1378                         set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1379         } else {
1380                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1381
1382         }
1383 }
1384
1385 static void
1386 on_account_inserted (TnyAccountStore *accoust_store,
1387                      TnyAccount *account,
1388                      gpointer user_data)
1389 {
1390         /* Transport accounts and local ones (MMC and the Local
1391            folders account do now cause menu changes */
1392         if (TNY_IS_STORE_ACCOUNT (account) && 
1393             modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1394                 /* Update menus */
1395                 update_menus (MODEST_MAIN_WINDOW (user_data));
1396         }
1397 }
1398
1399 static void
1400 on_default_account_changed (ModestAccountMgr* mgr,
1401                             gpointer user_data)
1402 {
1403         update_menus (MODEST_MAIN_WINDOW (user_data));
1404 }
1405
1406 static void
1407 on_account_removed (TnyAccountStore *accoust_store,
1408                      TnyAccount *account,
1409                      gpointer user_data)
1410 {
1411         /* Transport accounts and local ones (MMC and the Local
1412            folders account do now cause menu changes */
1413         if (TNY_IS_STORE_ACCOUNT (account) && 
1414             modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1415                 update_menus (MODEST_MAIN_WINDOW (user_data));
1416 }
1417
1418 static void
1419 on_account_changed (TnyAccountStore *account_store,
1420                     TnyAccount *account,
1421                     gpointer user_data)
1422 {
1423         ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1424
1425         /* Transport accounts and local ones (MMC and the Local
1426            folders account do now cause menu changes */
1427         if (TNY_IS_STORE_ACCOUNT (account)) {
1428                 /* Update the menus as well, name could change */
1429                 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1430                         update_menus (MODEST_MAIN_WINDOW (win));
1431         }
1432 }
1433
1434 /* 
1435  * This function manages the key events used to navigate between
1436  * header and folder views (when the window is in split view)
1437  *
1438  * FROM         KEY        ACTION
1439  * -------------------------------------------------
1440  * HeaderView   GDK_Left   Move focus to folder view
1441  * FolderView   GDK_Right  Move focus to header view
1442  *
1443  * There is no need to scroll to selected row, the widgets will be the
1444  * responsibles of doing that (probably managing the focus-in event
1445  */
1446 static gboolean 
1447 on_inner_widgets_key_pressed (GtkWidget *widget,
1448                               GdkEventKey *event,
1449                               gpointer user_data)
1450 {
1451         ModestMainWindowPrivate *priv;
1452
1453         if (event->type == GDK_KEY_RELEASE)
1454                 return FALSE;
1455
1456         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1457
1458         /* Do nothing if we're in SIMPLE style */
1459         if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1460                 return FALSE;
1461
1462         if (MODEST_IS_HEADER_VIEW (widget)) {
1463                 if (event->keyval == GDK_Left)
1464                         gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1465                 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1466                         guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1467                         if (selected_headers > 1) {
1468                                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1469                                 return TRUE;
1470                         } else {
1471                                 GtkTreePath * cursor_path;
1472                                 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1473                                 if (cursor_path == NULL) {
1474                                         GtkTreeSelection *selection;
1475                                         GList *list;
1476                                         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1477                                         list = gtk_tree_selection_get_selected_rows (selection, NULL);
1478
1479                                         if (list != NULL)
1480                                                 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1481                                         g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1482                                         g_list_free (list);
1483                                 }
1484                         }
1485                 }
1486         } else if (MODEST_IS_FOLDER_VIEW (widget) && (event->keyval == GDK_Right || event->keyval == GDK_Left)) {
1487 #if GTK_CHECK_VERSION(2, 8, 0) /* TODO: gtk_tree_view_get_visible_range() is only available in GTK+ 2.8 */
1488                 GtkTreePath *selected_path = NULL;
1489                 GtkTreePath *start_path = NULL;
1490                 GtkTreePath *end_path = NULL;
1491                 GList *selected;
1492                 GtkTreeSelection *selection;
1493
1494                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1495                 selected = gtk_tree_selection_get_selected_rows (selection, NULL);
1496                 if (selected != NULL) {
1497                         selected_path = (GtkTreePath *) selected->data;
1498                         if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (priv->header_view),
1499                                                              &start_path,
1500                                                              &end_path)) {
1501                                 
1502                                 if ((gtk_tree_path_compare (start_path, selected_path) != -1) ||
1503                                     (gtk_tree_path_compare (end_path, selected_path) != 1)) {
1504                                         
1505                                         /* Scroll to first path */
1506                                         gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->header_view),
1507                                                                       selected_path,
1508                                                                       NULL,
1509                                                                       TRUE,
1510                                                                       0.5,
1511                                                                       0.0);
1512                                 }
1513                         }
1514                         if (start_path)
1515                                 gtk_tree_path_free (start_path);
1516                         if (end_path)
1517                                 gtk_tree_path_free (end_path);
1518                         g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
1519                         g_list_free (selected);
1520                 }
1521 #endif /* GTK_CHECK_VERSION */
1522                         /* fix scroll */
1523                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1524         }
1525
1526         return FALSE;
1527 }
1528
1529 static GtkWidget *
1530 create_empty_view (void)
1531 {
1532         GtkLabel *label = NULL;
1533         GtkWidget *align = NULL;
1534
1535         align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1536         label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1537         gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);      
1538         gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1539
1540         return GTK_WIDGET(align);
1541 }
1542
1543
1544 gboolean
1545 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1546 {
1547         ModestMainWindowPrivate *priv = NULL;
1548         
1549         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1550
1551         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1552
1553         return priv->send_receive_in_progress;
1554 }
1555
1556 void 
1557 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1558 {
1559         GtkAction *action = NULL;
1560         GtkWidget *widget = NULL;
1561         ModestMainWindowPrivate *priv = NULL;
1562                 
1563         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1564         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1565         
1566         priv->send_receive_in_progress  = TRUE;
1567
1568         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1569         gtk_action_set_sensitive (action, FALSE);
1570 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1571 /*      gtk_action_set_sensitive (action, FALSE); */
1572         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1573         gtk_widget_set_sensitive (widget, FALSE);
1574
1575
1576 void 
1577 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1578 {
1579         GtkAction *action = NULL;
1580         GtkWidget *widget = NULL;
1581         ModestMainWindowPrivate *priv = NULL;
1582
1583         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1584         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1585
1586         priv->send_receive_in_progress  = FALSE;
1587
1588         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1589         gtk_action_set_sensitive (action, TRUE);
1590 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu");     */
1591 /*      gtk_action_set_sensitive (action, TRUE); */
1592         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1593         gtk_widget_set_sensitive (widget, TRUE);
1594 }
1595
1596
1597 static void
1598 on_msg_count_changed (ModestHeaderView *header_view,
1599                       TnyFolder *folder,
1600                       TnyFolderChange *change,
1601                       ModestMainWindow *main_window)
1602 {
1603         gboolean refilter = FALSE;
1604         gboolean folder_empty = FALSE;
1605         gboolean all_marked_as_deleted = FALSE;
1606         ModestMainWindowPrivate *priv;
1607
1608         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1609         g_return_if_fail (TNY_IS_FOLDER(folder));
1610         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1611
1612         if (change != NULL) {
1613                 TnyFolderChangeChanged changed;
1614
1615                 changed = tny_folder_change_get_changed (change);
1616                 /* If something changes */
1617                 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1618                         folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
1619                 else
1620                         folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
1621
1622                 /* Play a sound (if configured) and make the LED blink  */
1623                 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1624                         modest_platform_push_email_notification ();
1625                 }
1626
1627                 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
1628                         refilter = TRUE;
1629         } else {
1630                 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
1631         }
1632
1633         /* Check if all messages are marked to be deleted */
1634         all_marked_as_deleted = modest_header_view_is_empty (header_view);
1635         folder_empty = folder_empty || all_marked_as_deleted;
1636
1637         /* Set contents style of headers view */
1638         if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY ||
1639             priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS) {
1640                 if (folder_empty)  {
1641                         modest_main_window_set_contents_style (main_window,
1642                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1643                         gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1644                 } else {
1645                         modest_main_window_set_contents_style (main_window,
1646                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1647                 }
1648         }
1649
1650         if (refilter)
1651                 modest_header_view_refilter (header_view);
1652 }
1653
1654
1655 void 
1656 modest_main_window_set_contents_style (ModestMainWindow *self, 
1657                                        ModestMainWindowContentsStyle style)
1658 {
1659         ModestMainWindowPrivate *priv;
1660
1661         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1662
1663         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1664
1665         /* We allow to set the same content style than the previously
1666            set if there are details, because it could happen when we're
1667            selecting different accounts consecutively */
1668         if ((priv->contents_style == style) &&
1669             (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1670                 return;
1671
1672         /* Remove previous child. Delete it if it was an account
1673            details widget */
1674         GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1675         if (content) {
1676                 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1677                         gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1678                 }
1679                 
1680                 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1681         }
1682
1683         priv->contents_style = style;
1684
1685         switch (priv->contents_style) {
1686         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_FOLDERS:
1687                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->folder_view));
1688                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1689                                                       TRUE);
1690                 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1691                 break;
1692         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1693                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1694                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1695                                                       TRUE);
1696                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1697                 gtk_widget_show (GTK_WIDGET (priv->header_view));
1698                 break;
1699         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1700                 g_warning ("This view is not supported in Fremantle style");
1701                 break;
1702         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1703                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1704                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1705                                                       FALSE);
1706                 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1707                         gtk_widget_grab_focus (GTK_WIDGET (priv->empty_view));
1708                 break;
1709         default:
1710                 g_return_if_reached ();
1711         }
1712
1713         /* Show */
1714         gtk_widget_show_all (priv->contents_widget);
1715 }
1716
1717 ModestMainWindowContentsStyle
1718 modest_main_window_get_contents_style (ModestMainWindow *self)
1719 {
1720         ModestMainWindowPrivate *priv;
1721
1722         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1723
1724         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1725         return priv->contents_style;
1726 }
1727
1728
1729 static void 
1730 on_configuration_key_changed (ModestConf* conf, 
1731                               const gchar *key, 
1732                               ModestConfEvent event,
1733                               ModestConfNotificationId id, 
1734                               ModestMainWindow *self)
1735 {
1736         /* TODO: remove this handler. Now we don't support details view, 
1737          *  so this must be removed */
1738
1739         return;
1740 }
1741
1742 static gboolean
1743 set_toolbar_transfer_mode (ModestMainWindow *self)
1744 {
1745         ModestMainWindowPrivate *priv = NULL;
1746         
1747         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1748
1749         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1750
1751         set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1752         
1753         if (priv->progress_bar_timeout > 0) {
1754                 g_source_remove (priv->progress_bar_timeout);
1755                 priv->progress_bar_timeout = 0;
1756         }
1757
1758         return FALSE;
1759 }
1760
1761 static void 
1762 set_toolbar_mode (ModestMainWindow *self, 
1763                   ModestToolBarModes mode)
1764 {
1765         ModestWindowPrivate *parent_priv = NULL;
1766         ModestMainWindowPrivate *priv = NULL;
1767         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1768         
1769         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1770
1771         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1772         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1773
1774         /* In case this was called before the toolbar exists: */
1775         if (!(parent_priv->toolbar))
1776                 return;
1777
1778         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
1779         
1780         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1781         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1782         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1783
1784         /* Sets current toolbar mode */
1785         priv->current_toolbar_mode = mode;
1786
1787         /* Checks the dimming rules */
1788         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1789         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1790
1791         /* Show and hide toolbar items */
1792         switch (mode) {
1793         case TOOLBAR_MODE_NORMAL:
1794                 if (sort_action)
1795                         gtk_action_set_visible (sort_action, TRUE);
1796                 if (refresh_action)
1797                         gtk_action_set_visible (refresh_action, TRUE);
1798                 if (priv->progress_toolitem) {
1799                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1800                         gtk_widget_hide (priv->progress_toolitem);
1801                 }
1802                 if (priv->progress_bar)
1803                         gtk_widget_hide (priv->progress_bar);
1804                 
1805                 if (cancel_action)
1806                         gtk_action_set_visible (cancel_action, FALSE);
1807
1808                 /* Hide toolbar if optimized view is enabled */
1809                 if (priv->optimized_view)
1810                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1811                 break;
1812         case TOOLBAR_MODE_TRANSFER:
1813                 if (sort_action)
1814                         gtk_action_set_visible (sort_action, FALSE);
1815                 if (refresh_action)
1816                         gtk_action_set_visible (refresh_action, FALSE);
1817                 if (cancel_action)
1818                         gtk_action_set_visible (cancel_action, TRUE);
1819                 if (priv->progress_bar)
1820                         gtk_widget_show (priv->progress_bar);
1821                 if (priv->progress_toolitem) {
1822                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1823                         gtk_widget_show (priv->progress_toolitem);
1824                 }
1825
1826                 /* Show toolbar if it's hiden (optimized view ) */
1827                 if (priv->optimized_view)
1828                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1829                 break;
1830         default:
1831                 g_return_if_reached ();
1832         }
1833 }
1834
1835 gboolean
1836 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
1837 {
1838         ModestMainWindowPrivate *priv;
1839
1840         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1841         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1842
1843         return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
1844 }
1845
1846 static void
1847 cancel_progressbar (GtkToolButton *toolbutton,
1848                     ModestMainWindow *self)
1849 {
1850         GSList *tmp;
1851         ModestMainWindowPrivate *priv;
1852         
1853         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1854
1855         /* Get operation observers and cancel all the operations */
1856         tmp = priv->progress_widgets;
1857         while (tmp) {
1858                 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1859                 tmp=g_slist_next(tmp);
1860         }
1861 }
1862
1863 static gboolean
1864 observers_empty (ModestMainWindow *self)
1865 {
1866         GSList *tmp = NULL;
1867         ModestMainWindowPrivate *priv;
1868         gboolean is_empty = TRUE;
1869         guint pending_ops = 0;
1870  
1871         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1872         tmp = priv->progress_widgets;
1873
1874         /* Check all observers */
1875         while (tmp && is_empty)  {
1876                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1877                 is_empty = pending_ops == 0;
1878                 
1879                 tmp = g_slist_next(tmp);
1880         }
1881         
1882         return is_empty;
1883 }
1884
1885
1886 /**
1887  * Gets the toolbar mode needed for each mail operation. It stores in
1888  * @mode_changed if the toolbar mode has changed or not
1889  */
1890 static ModestToolBarModes
1891 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
1892                                       ModestMailOperation *mail_op,
1893                                       gboolean *mode_changed)
1894 {
1895         ModestToolBarModes mode;
1896         ModestMainWindowPrivate *priv;
1897
1898         *mode_changed = FALSE;
1899         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1900
1901         /* Get toolbar mode from operation id*/
1902         switch (modest_mail_operation_get_type_operation (mail_op)) {
1903         case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
1904         case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1905                 mode = TOOLBAR_MODE_TRANSFER;
1906                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
1907                         *mode_changed = TRUE;
1908                 break;
1909         default:
1910                 mode = TOOLBAR_MODE_NORMAL;             
1911         }
1912         return mode;
1913 }
1914
1915 static void 
1916 on_mail_operation_started (ModestMailOperation *mail_op,
1917                            gpointer user_data)
1918 {
1919         ModestMainWindow *self;
1920         ModestMailOperationTypeOperation op_type;
1921         ModestMainWindowPrivate *priv;
1922         ModestToolBarModes mode;
1923         GSList *tmp;
1924         gboolean mode_changed = FALSE;
1925         TnyAccount *account = NULL;
1926
1927         self = MODEST_MAIN_WINDOW (user_data);
1928         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1929
1930         /* Do not show progress for receiving operations if the
1931            account is the local account or the MMC one */
1932         op_type = modest_mail_operation_get_type_operation (mail_op);
1933         account = modest_mail_operation_get_account (mail_op);
1934         if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
1935                 gboolean is_remote;
1936
1937                 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
1938                               modest_tny_account_is_memory_card_account (account));
1939                 if (!is_remote) {
1940                         g_object_unref (account);
1941                         return;
1942                 }
1943
1944                 /* Show information banner. Remove old timeout */
1945                 if (priv->opening_banner_timeout > 0) {
1946                         g_source_remove (priv->opening_banner_timeout);
1947                         priv->opening_banner_timeout = 0;
1948                 }
1949                 /* Create a new timeout */
1950                 priv->opening_banner_timeout = 
1951                         g_timeout_add (2000, show_opening_banner, self);
1952         }
1953
1954         /* Not every mail operation has account, noop does not */
1955         if (account)
1956                 g_object_unref (account);
1957                
1958         /* Get toolbar mode from operation id*/
1959         mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
1960
1961         /* Add operation observers and change toolbar if neccessary*/
1962         tmp = priv->progress_widgets;
1963         if (mode == TOOLBAR_MODE_TRANSFER) {
1964                 if (mode_changed) {
1965                         GObject *source = modest_mail_operation_get_source(mail_op);
1966                         if (G_OBJECT (self) == source) {
1967                                 set_toolbar_transfer_mode(self);
1968                         }
1969                         g_object_unref (source);
1970                 }
1971
1972                 while (tmp) {
1973                         modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1974                                                               mail_op);
1975                         tmp = g_slist_next (tmp);
1976                 }
1977         }
1978
1979         /* Update the main menu as well, we need to explicitely do
1980            this in order to enable/disable accelerators */
1981         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1982 }
1983
1984 static void 
1985 on_mail_operation_finished (ModestMailOperation *mail_op,
1986                             gpointer user_data)
1987 {
1988         ModestToolBarModes mode;
1989         ModestMailOperationTypeOperation op_type;
1990         GSList *tmp = NULL;
1991         ModestMainWindow *self;
1992         gboolean mode_changed;
1993         TnyAccount *account = NULL;
1994         ModestMainWindowPrivate *priv;
1995
1996         self = MODEST_MAIN_WINDOW (user_data);
1997         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1998
1999         /* The mail operation was not added to the progress objects if
2000            the account was the local account or the MMC one */
2001         op_type = modest_mail_operation_get_type_operation (mail_op);
2002         account = modest_mail_operation_get_account (mail_op);
2003         if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2004                 gboolean is_remote;
2005
2006                 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2007                               modest_tny_account_is_memory_card_account (account));
2008                 if (!is_remote) {
2009                         g_object_unref (account);
2010                         return;
2011                 }
2012
2013                 /* Remove old timeout */
2014                 if (priv->opening_banner_timeout > 0) {
2015                         g_source_remove (priv->opening_banner_timeout);
2016                         priv->opening_banner_timeout = 0;
2017                 }
2018
2019                 /* Remove the banner if exists */
2020                 if (priv->opening_banner) {
2021                         gtk_widget_destroy (priv->opening_banner);
2022                         priv->opening_banner = NULL;
2023                 }
2024         }
2025
2026         /* Not every mail operation has account, noop does not */
2027         if (account)
2028                 g_object_unref (account);
2029
2030         /* Get toolbar mode from operation id*/
2031         mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2032
2033         /* Change toolbar mode */
2034         tmp = priv->progress_widgets;
2035         if (mode == TOOLBAR_MODE_TRANSFER) {                    
2036                 while (tmp) {
2037                         modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2038                                                                  mail_op);
2039                         tmp = g_slist_next (tmp);
2040                 }
2041                 
2042                 /* If no more operations are being observed, NORMAL mode is enabled again */
2043                 if (observers_empty (self)) {
2044                         set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);                           
2045                 }
2046         }
2047 }
2048
2049 static void
2050 on_queue_changed (ModestMailOperationQueue *queue,
2051                   ModestMailOperation *mail_op,
2052                   ModestMailOperationQueueNotification type,
2053                   ModestMainWindow *self)
2054 {
2055         ModestMainWindowPrivate *priv;
2056
2057         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2058
2059         if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2060                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2061                                                                G_OBJECT (mail_op),
2062                                                                "operation-started",
2063                                                                G_CALLBACK (on_mail_operation_started),
2064                                                                self);
2065                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2066                                                                G_OBJECT (mail_op),
2067                                                                "operation-finished",
2068                                                                G_CALLBACK (on_mail_operation_finished),
2069                                                                self);
2070         } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2071                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2072                                                                   G_OBJECT (mail_op),
2073                                                                   "operation-started");
2074                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2075                                                                   G_OBJECT (mail_op),
2076                                                                   "operation-finished");
2077         }
2078 }
2079
2080 static void
2081 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2082 {
2083         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2084         GtkAction *action;
2085         ModestAccountMgr *mgr;
2086         ModestAccountSettings *settings;
2087         ModestServerAccountSettings *store_settings = NULL;
2088
2089 /*      GtkWidget *folder_window; */
2090
2091 /*      folder_window = GTK_WIDGET (modest_folder_window_new (NULL)); */
2092 /*      modest_window_mgr_register_window (modest_runtime_get_window_mgr (),  */
2093 /*                                         MODEST_WINDOW (folder_window), */
2094 /*                                         MODEST_WINDOW (self)); */
2095 /*      gtk_widget_show (folder_window); */
2096         GtkWidget *accounts_window;
2097
2098         accounts_window = GTK_WIDGET (modest_accounts_window_new ());
2099         modest_window_mgr_register_window (modest_runtime_get_window_mgr (),
2100                                            MODEST_WINDOW (accounts_window),
2101                                            MODEST_WINDOW (self));
2102         gtk_widget_show (accounts_window);
2103
2104         /* Get account data */
2105         mgr = modest_runtime_get_account_mgr ();
2106         settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2107         if (settings)
2108                 store_settings = modest_account_settings_get_store_settings (settings);
2109
2110         /* Set the new visible & active account */
2111         if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) { 
2112                 const gchar *account_name;
2113
2114                 account_name = modest_account_settings_get_account_name (settings);
2115
2116                 modest_folder_view_set_account_id_of_visible_server_account 
2117                         (priv->folder_view,
2118                          modest_server_account_settings_get_account_name (store_settings));
2119                 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2120                 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2121
2122 /*              modest_folder_window_set_account (MODEST_FOLDER_WINDOW (folder_window), acc_name); */
2123
2124                 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2125                 if (action != NULL) {
2126                         if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2127                                 modest_utils_toggle_action_set_active_block_notify (
2128                                         GTK_TOGGLE_ACTION (action),
2129                                         TRUE);
2130                         }
2131                 }
2132         }
2133         
2134         /* Free */
2135         if (settings) {
2136                 g_object_unref (store_settings);
2137                 g_object_unref (settings);
2138         }
2139
2140 }
2141
2142 /* Make sure that at least one account is "viewed": */
2143 static void
2144 set_at_least_one_account_visible(ModestMainWindow *self)
2145 {
2146         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2147         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2148
2149         if (!(priv->folder_view)) {
2150                 /* It is too early to do this. */
2151                 return; 
2152         }
2153         
2154         const gchar *active_server_account_name = 
2155                 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2156         
2157         if (!active_server_account_name ||
2158                 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2159         {
2160                 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2161                 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2162                 if (default_modest_name) {
2163                         set_account_visible (self, default_modest_name);
2164                 } else if (first_modest_name) {
2165                         set_account_visible (self, first_modest_name);
2166                 }
2167                 g_free (first_modest_name);
2168                 g_free (default_modest_name);
2169         }
2170 }
2171
2172 static void 
2173 on_show_account_action_toggled  (GtkToggleAction *action,
2174                                    gpointer user_data)
2175 {
2176         ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2177
2178         const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2179         if (gtk_toggle_action_get_active (action))
2180                 set_account_visible (self, acc_name);
2181 }
2182
2183 static void
2184 refresh_account (const gchar *account_name)
2185 {
2186         ModestWindow *win;
2187         
2188         /* win must already exists here, obviously */ 
2189         win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2190                                                  FALSE);
2191         if (!win) {
2192                 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2193                 return;
2194         }
2195         
2196         /* If account_name == NULL, we must update all (option All) */
2197         if (!account_name)
2198                 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2199         else
2200                 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2201         
2202 }
2203
2204 static void 
2205 on_refresh_account_action_activated  (GtkAction *action,
2206                                       gpointer user_data)
2207 {
2208         refresh_account ((const gchar*) user_data);
2209 }
2210
2211 static void
2212 on_send_receive_csm_activated (GtkMenuItem *item,
2213                                gpointer user_data)
2214 {
2215         refresh_account ((const gchar*) user_data);
2216 }
2217
2218 static gboolean
2219 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2220 {
2221         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2222
2223         hildon_banner_show_information (NULL, NULL, _CS("ckct_ib_cannot_zoom_here"));
2224         return FALSE;
2225
2226 }
2227
2228 static gboolean
2229 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2230 {
2231         ModestMainWindow *main_window = NULL;
2232         
2233         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2234         main_window = MODEST_MAIN_WINDOW (userdata);
2235         
2236         /* Update toolbar dimming state */
2237         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2238         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2239
2240         return FALSE;
2241 }
2242
2243 static gboolean
2244 on_header_view_focus_in (GtkWidget *widget,
2245                          GdkEventFocus *event,
2246                          gpointer userdata)
2247 {
2248         ModestMainWindow *main_window = NULL;
2249
2250         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2251
2252         main_window = MODEST_MAIN_WINDOW (userdata);
2253
2254         /* Update toolbar dimming state */
2255         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2256         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2257
2258         return FALSE;
2259 }
2260
2261 static void 
2262 on_folder_selection_changed (ModestFolderView *folder_view,
2263                              TnyFolderStore *folder_store, 
2264                              gboolean selected,
2265                              ModestMainWindow *main_window)
2266 {
2267         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2268         GtkAction *action = NULL;
2269         gboolean show_reply = TRUE;
2270         gboolean show_forward = TRUE;
2271         gboolean show_cancel_send = FALSE;
2272         gboolean show_clipboard = TRUE;
2273         gboolean show_delete = TRUE;
2274
2275         if (selected) {
2276                 if (TNY_IS_ACCOUNT (folder_store)) {
2277                         show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2278                 } else if (TNY_IS_FOLDER (folder_store)) {
2279                         if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2280                                 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2281                                         TNY_FOLDER (folder_store));
2282                                 switch (folder_type) {
2283                                 case TNY_FOLDER_TYPE_DRAFTS:
2284                                         show_clipboard = show_delete = TRUE;
2285                                         show_reply = show_forward = show_cancel_send = FALSE;
2286                                         break;
2287                                 case TNY_FOLDER_TYPE_SENT:
2288                                         show_forward = show_clipboard = show_delete = TRUE;
2289                                         show_reply = show_cancel_send = FALSE;
2290                                         break;
2291                                 case TNY_FOLDER_TYPE_OUTBOX:
2292                                         show_clipboard = show_delete = show_cancel_send = TRUE;
2293                                         show_reply = show_forward = FALSE;
2294                                         break;
2295                                 case TNY_FOLDER_TYPE_INVALID:
2296                                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2297                                         break;
2298                                 default:
2299                                         show_reply = show_forward = show_clipboard = show_delete = TRUE;
2300                                         show_cancel_send = FALSE;
2301                                 }
2302                         } else {
2303                                 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2304                                 show_cancel_send = FALSE;
2305                         }
2306                 }
2307         }
2308
2309         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2310         gtk_action_set_visible (action, show_reply);
2311         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2312         gtk_action_set_visible (action, show_reply);
2313         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2314         gtk_action_set_visible (action, show_forward);
2315         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2316         gtk_action_set_visible (action, show_cancel_send);
2317         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2318         gtk_action_set_visible (action, show_delete);
2319
2320 }
2321
2322 gboolean 
2323 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2324                                                    GtkTreeModel *model,
2325                                                    GtkTreeRowReference *row_reference,
2326                                                    ModestMainWindow *self)
2327 {
2328         ModestMainWindowPrivate *priv = NULL;
2329         GtkTreeModel *header_model = NULL;
2330         GtkTreePath *path = NULL;
2331
2332         g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2333         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2334         g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2335
2336         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2337         header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2338
2339         /* Do nothing if we changed the folder in the main view */
2340         if (header_model != model)
2341                 return FALSE;
2342
2343         /* Select the message in the header view */
2344         path = gtk_tree_row_reference_get_path (row_reference);
2345         gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2346                                   path, NULL, FALSE);
2347         gtk_tree_path_free (path);
2348
2349         return TRUE;
2350 }
2351
2352 static void
2353 updating_banner_destroyed (gpointer data,
2354                            GObject *where_the_object_was)
2355 {
2356         ModestMainWindowPrivate *priv = NULL;
2357
2358         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2359
2360         priv->updating_banner = NULL;
2361 }
2362
2363 static gboolean
2364 show_updating_banner (gpointer user_data)
2365 {
2366         ModestMainWindowPrivate *priv = NULL;
2367
2368         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2369
2370         if (priv->updating_banner == NULL) {
2371
2372                 /* We're outside the main lock */
2373                 gdk_threads_enter ();
2374                 priv->updating_banner = 
2375                         modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2376                                                           _CS ("ckdg_pb_updating"));
2377
2378                 /* We need this because banners in Maemo could be
2379                    destroyed by dialogs so we need to properly update
2380                    our reference to it */
2381                 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2382                                    updating_banner_destroyed,
2383                                    user_data);
2384                 gdk_threads_leave ();
2385         }
2386
2387         /* Remove timeout */
2388         priv->updating_banner_timeout = 0;
2389         return FALSE;
2390 }
2391
2392 /**
2393  * We use this function to show/hide a progress banner showing
2394  * "Updating" while the header view is being filled. We're not showing
2395  * it unless the update takes more than 2 seconds
2396  *
2397  * If starting = TRUE then the refresh is starting, otherwise it means
2398  * that is has just finished
2399  */
2400 static void 
2401 on_updating_msg_list (ModestHeaderView *header_view,
2402                       gboolean starting,
2403                       gpointer user_data)
2404 {
2405         ModestMainWindowPrivate *priv = NULL;
2406
2407         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2408         
2409         /* Remove old timeout */
2410         if (priv->updating_banner_timeout > 0) {
2411                 g_source_remove (priv->updating_banner_timeout);
2412                 priv->updating_banner_timeout = 0;
2413         }
2414
2415         /* Create a new timeout */
2416         if (starting) {
2417                 priv->updating_banner_timeout = 
2418                         g_timeout_add (2000, show_updating_banner, user_data);
2419         } else {
2420                 /* Remove the banner if exists */
2421                 if (priv->updating_banner) {
2422                         gtk_widget_destroy (priv->updating_banner);
2423                         priv->updating_banner = NULL;
2424                 }
2425         }
2426 }
2427
2428 static void on_folder_view_row_activated (GtkTreeView *tree_view,
2429                                           GtkTreePath *tree_path,
2430                                           GtkTreeViewColumn *column,
2431                                           gpointer userdata)
2432 {
2433         GtkTreeModel  *model;
2434         GtkTreeIter iter;
2435         TnyFolderStore *folder_store = NULL;
2436         ModestMainWindow *self = (ModestMainWindow *) userdata;
2437         ModestMainWindowPrivate *priv = NULL;
2438
2439         g_return_if_fail (MODEST_IS_MAIN_WINDOW(self));
2440         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2441
2442         model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
2443
2444         if (gtk_tree_model_get_iter (model, &iter, tree_path)) {
2445                 gtk_tree_model_get (model, &iter,
2446                                     TNY_GTK_FOLDER_STORE_TREE_MODEL_INSTANCE_COLUMN, &folder_store,
2447                                     -1);
2448                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
2449                         modest_header_view_set_folder (MODEST_HEADER_VIEW (priv->header_view), 
2450                                                        TNY_FOLDER (folder_store), TRUE, MODEST_WINDOW (self),
2451                                                        NULL, NULL);
2452                         modest_main_window_set_contents_style (MODEST_MAIN_WINDOW (self),
2453                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2454                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2455                                                       G_OBJECT(priv->header_view),
2456                                                       MODEST_CONF_HEADER_VIEW_KEY);
2457                         on_msg_count_changed (MODEST_HEADER_VIEW (priv->header_view), TNY_FOLDER (folder_store), NULL, self);
2458                 }
2459
2460                 if (folder_store)
2461                         g_object_unref (folder_store);
2462         }
2463
2464         g_debug ("FOLDER VIEW CELL ACTIVATED");
2465         
2466 }
2467
2468 gboolean
2469 modest_main_window_screen_is_on (ModestMainWindow *self)
2470 {
2471         ModestMainWindowPrivate *priv = NULL;
2472
2473         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2474
2475         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2476         
2477         return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2478 }
2479
2480 static void
2481 remove_banners (ModestMainWindow *window)
2482 {
2483         ModestMainWindowPrivate *priv;
2484
2485         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2486
2487         if (priv->opening_banner_timeout > 0) {
2488                 g_source_remove (priv->opening_banner_timeout);
2489                 priv->opening_banner_timeout = 0;
2490         }
2491
2492         if (priv->opening_banner != NULL) {
2493                 gtk_widget_destroy (priv->opening_banner);
2494                 priv->opening_banner = NULL;
2495         }
2496         
2497         if (priv->updating_banner_timeout > 0) {
2498                 g_source_remove (priv->updating_banner_timeout);
2499                 priv->updating_banner_timeout = 0;
2500         }
2501
2502         if (priv->updating_banner != NULL) {
2503                 gtk_widget_destroy (priv->updating_banner);
2504                 priv->updating_banner = NULL;
2505         }       
2506 }
2507
2508
2509 static void
2510 on_window_hide (GObject    *gobject,
2511                 GParamSpec *arg1,
2512                 gpointer    user_data)
2513 {
2514         g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2515
2516         if (!GTK_WIDGET_VISIBLE (gobject)) {
2517                 TnyFolderStore *folder_store;
2518                 ModestMainWindowPrivate *priv;
2519                 
2520                 /* Remove the currently shown banners */
2521                 remove_banners (MODEST_MAIN_WINDOW (gobject));
2522
2523                 /* Force the folder view to sync the currently selected folder
2524                    to save the read/unread status and to expunge messages */
2525                 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
2526                 folder_store = modest_folder_view_get_selected (priv->folder_view);
2527                 if (TNY_IS_FOLDER (folder_store)) {
2528                         ModestMailOperation *mail_op;
2529                         
2530                         mail_op = modest_mail_operation_new (NULL);
2531                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2532                                                          mail_op);
2533                         modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE, NULL, NULL);
2534                         g_object_unref (mail_op);
2535                         g_object_unref (folder_store);
2536                 }
2537         }
2538 }
2539
2540 static void
2541 on_window_destroy (GtkObject *widget, 
2542                    gpointer user_data)
2543 {
2544         g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
2545
2546         remove_banners (MODEST_MAIN_WINDOW (widget));
2547 }
2548
2549 static void
2550 opening_banner_destroyed (gpointer data,
2551                            GObject *where_the_object_was)
2552 {
2553         ModestMainWindowPrivate *priv = NULL;
2554
2555         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2556
2557         priv->opening_banner = NULL;
2558 }
2559
2560 static gboolean
2561 show_opening_banner (gpointer user_data)
2562 {
2563         ModestMainWindowPrivate *priv = NULL;
2564
2565         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2566
2567         if (priv->opening_banner == NULL) {
2568
2569                 /* We're outside the main lock */
2570                 gdk_threads_enter ();
2571                 priv->opening_banner = 
2572                         modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2573                                                           _("mail_me_opening"));
2574
2575                 /* We need this because banners in Maemo could be
2576                    destroyed by dialogs so we need to properly update
2577                    our reference to it */
2578                 g_object_weak_ref (G_OBJECT (priv->opening_banner),
2579                                    opening_banner_destroyed,
2580                                    user_data);
2581
2582                 /* We need this because banners in Maemo could be
2583                    destroyed by dialogs so we need to properly update
2584                    our reference to it */
2585                 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2586                                    updating_banner_destroyed,
2587                                    user_data);
2588                 gdk_threads_leave ();
2589         }
2590
2591         /* Remove timeout */
2592         priv->opening_banner_timeout = 0;
2593         return FALSE;
2594 }