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