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