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