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