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