136ec53d938ec1050002c4dee24610c63c0e4f8d
[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 "modest-hildon-includes.h"
38 #include "modest-defs.h"
39 #include <string.h>
40
41 #include "widgets/modest-main-window.h"
42 #include "widgets/modest-msg-edit-window.h"
43 #include "widgets/modest-account-view-window.h"
44 #include "modest-runtime.h"
45 #include "modest-account-mgr-helpers.h"
46 #include "modest-platform.h"
47 #include "modest-widget-memory.h"
48 #include "modest-window-priv.h"
49 #include "modest-main-window-ui.h"
50 #include "modest-main-window-ui-dimming.h"
51 #include "modest-account-mgr.h"
52 #include "modest-tny-account.h"
53 #include "modest-conf.h"
54 #include <modest-maemo-utils.h>
55 #include "modest-tny-platform-factory.h"
56 #include "modest-tny-msg.h"
57 #include "modest-mail-operation.h"
58 #include "modest-icon-names.h"
59 #include "modest-progress-bar-widget.h"
60 #include "modest-text-utils.h"
61 #include "modest-ui-dimming-manager.h"
62 #include "maemo/modest-osso-state-saving.h"
63
64 #ifdef MODEST_HAVE_HILDON0_WIDGETS
65 #include <hildon-widgets/hildon-program.h>
66 #else
67 #include <hildon/hildon-program.h>
68 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
69
70 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
71
72 #define XALIGN 0.5
73 #define YALIGN 0.0
74 #define XSPACE 1
75 #define YSPACE 0
76
77 /* 'private'/'protected' functions */
78 static void modest_main_window_class_init    (ModestMainWindowClass *klass);
79 static void modest_main_window_init          (ModestMainWindow *obj);
80 static void modest_main_window_finalize      (GObject *obj);
81 static gboolean modest_main_window_window_state_event (GtkWidget *widget, 
82                                                            GdkEventWindowState *event, 
83                                                            gpointer userdata);
84
85 static void connect_signals (ModestMainWindow *self);
86
87 static void restore_settings (ModestMainWindow *self, gboolean do_folder_view_too);
88 static void save_state (ModestWindow *self);
89
90 static void modest_main_window_show_toolbar   (ModestWindow *window,
91                                                gboolean show_toolbar);
92
93 static void cancel_progressbar (GtkToolButton *toolbutton,
94                                 ModestMainWindow *self);
95
96 static void         on_queue_changed                     (ModestMailOperationQueue *queue,
97                                                           ModestMailOperation *mail_op,
98                                                           ModestMailOperationQueueNotification type,
99                                                           ModestMainWindow *self);
100
101 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
102
103 static void on_account_update                 (TnyAccountStore *account_store, 
104                                                const gchar *account_name,
105                                                gpointer user_data);
106
107 static gboolean on_inner_widgets_key_pressed  (GtkWidget *widget,
108                                                GdkEventKey *event,
109                                                gpointer user_data);
110
111 static void on_configuration_key_changed      (ModestConf* conf, 
112                                                const gchar *key, 
113                                                ModestConfEvent event, 
114                                                ModestMainWindow *self);
115
116 static void set_toolbar_mode                  (ModestMainWindow *self, 
117                                                ModestToolBarModes mode);
118
119 static gboolean set_toolbar_transfer_mode     (ModestMainWindow *self); 
120
121 static void on_show_account_action_activated      (GtkAction *action,
122                                                    gpointer user_data);
123
124 static void on_refresh_account_action_activated   (GtkAction *action,
125                                                    gpointer user_data);
126
127 static void on_send_receive_csm_activated         (GtkMenuItem *item,
128                                                    gpointer user_data);
129
130 static void
131 _on_msg_count_changed (ModestHeaderView *header_view,
132                        TnyFolder *folder,
133                        TnyFolderChange *change,
134                        ModestMainWindow *main_window);
135
136 static void
137 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
138
139
140 static GtkWidget * create_empty_view (void);
141
142
143 /* list my signals */
144 enum {
145         /* MY_SIGNAL_1, */
146         /* MY_SIGNAL_2, */
147         LAST_SIGNAL
148 };
149
150 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
151 struct _ModestMainWindowPrivate {
152         GtkWidget *msg_paned;
153         GtkWidget *main_paned;
154         GtkWidget *main_vbox;
155         GtkWidget *contents_widget;
156         GtkWidget *empty_view;
157
158         /* Progress observers */
159         GtkWidget        *progress_bar;
160         GSList           *progress_widgets;
161
162         /* Tollbar items */
163         GtkWidget   *progress_toolitem;
164         GtkWidget   *cancel_toolitem;
165         GtkWidget   *sort_toolitem;
166         GtkWidget   *refresh_toolitem;
167         ModestToolBarModes current_toolbar_mode;
168
169         /* Merge ids used to add/remove accounts to the ViewMenu*/
170         GByteArray *merge_ids;
171
172         /* On-demand widgets */
173         GtkWidget *accounts_popup;
174         GtkWidget *details_widget;
175
176         /* Optimized view enabled */
177         gboolean optimized_view;
178
179         /* Optimized view enabled */
180         gboolean send_receive_in_progress;
181
182         ModestHeaderView *header_view;
183         ModestFolderView *folder_view;
184
185         ModestMainWindowStyle style;
186         ModestMainWindowContentsStyle contents_style;
187
188         guint progress_bar_timeout;
189
190         /* Signal handler UIDs */
191         gint queue_changed_handler_uid; 
192         GList *queue_err_signals;
193 };
194 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
195                                                 MODEST_TYPE_MAIN_WINDOW, \
196                                                 ModestMainWindowPrivate))
197
198 typedef struct _GetMsgAsyncHelper {
199         ModestMainWindowPrivate *main_window_private;
200         guint action;
201         ModestTnyMsgReplyType reply_type;
202         ModestTnyMsgForwardType forward_type;
203         gchar *from;
204         TnyIterator *iter;
205 } GetMsgAsyncHelper;
206
207
208 /* globals */
209 static GtkWindowClass *parent_class = NULL;
210
211
212 /* Private actions */
213 /* This is the context sensitive menu: */
214 static const GtkActionEntry modest_folder_view_action_entries [] = {
215
216         /* Folder View CSM actions */
217         { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
218         { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
219         { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL,  G_CALLBACK (modest_ui_actions_on_paste)},
220         { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
221         { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
222         { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
223 };
224
225 static const GtkActionEntry modest_header_view_action_entries [] = {
226
227         /* Header View CSM actions */
228         { "HeaderViewCSMOpen",          NULL,  N_("mcen_me_inbox_open"),        NULL,       NULL, G_CALLBACK (modest_ui_actions_on_open) },
229         { "HeaderViewCSMReply",         NULL,  N_("mcen_me_inbox_reply"),       NULL,      NULL, G_CALLBACK (modest_ui_actions_on_reply) },
230         { "HeaderViewCSMReplyAll",      NULL,  N_("mcen_me_inbox_replytoall"),  NULL,      NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
231         { "HeaderViewCSMForward",       NULL,  N_("mcen_me_inbox_forward"),     NULL,      NULL, G_CALLBACK (modest_ui_actions_on_forward) },
232         { "HeaderViewCSMCut",           NULL,  N_("mcen_me_inbox_cut"),         "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
233         { "HeaderViewCSMCopy",          NULL,  N_("mcen_me_inbox_copy"),        "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
234         { "HeaderViewCSMPaste",         NULL,  N_("mcen_me_inbox_paste"),       "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
235         { "HeaderViewCSMDelete",        NULL,  N_("mcen_me_inbox_delete"),      NULL,      NULL, G_CALLBACK (modest_ui_actions_on_delete) },
236         { "HeaderViewCSMCancelSending", NULL,  N_("mcen_me_outbox_cancelsend"), NULL,      NULL, NULL },
237         { "HeaderViewCSMHelp",          NULL,  N_("mcen_me_inbox_help"),        NULL,      NULL, G_CALLBACK (modest_ui_actions_on_help) },
238 };
239
240 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
241         { "ToolbarToggleView", MODEST_STOCK_SPLIT_VIEW, N_("gqn_toolb_rss_fldonoff"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), FALSE },
242 };
243
244 /************************************************************************/
245
246 GType
247 modest_main_window_get_type (void)
248 {
249         static GType my_type = 0;
250         if (!my_type) {
251                 static const GTypeInfo my_info = {
252                         sizeof(ModestMainWindowClass),
253                         NULL,           /* base init */
254                         NULL,           /* base finalize */
255                         (GClassInitFunc) modest_main_window_class_init,
256                         NULL,           /* class finalize */
257                         NULL,           /* class data */
258                         sizeof(ModestMainWindow),
259                         1,              /* n_preallocs */
260                         (GInstanceInitFunc) modest_main_window_init,
261                         NULL
262                 };
263                 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
264                                                   "ModestMainWindow",
265                                                   &my_info, 0);
266         }
267         return my_type;
268 }
269
270 static void
271 modest_main_window_class_init (ModestMainWindowClass *klass)
272 {
273         GObjectClass *gobject_class;
274         gobject_class = (GObjectClass*) klass;
275         ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
276
277         parent_class            = g_type_class_peek_parent (klass);
278         gobject_class->finalize = modest_main_window_finalize;
279
280         g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
281         
282         modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
283         modest_window_class->save_state_func = save_state;
284         modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
285         modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
286 }
287
288 static void
289 modest_main_window_init (ModestMainWindow *obj)
290 {
291         ModestMainWindowPrivate *priv;
292
293         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
294
295         priv->queue_err_signals = NULL;
296         priv->msg_paned    = NULL;
297         priv->main_paned   = NULL;      
298         priv->main_vbox    = NULL;
299         priv->header_view  = NULL;
300         priv->folder_view  = NULL;
301         priv->contents_widget  = NULL;
302         priv->accounts_popup  = NULL;
303         priv->details_widget  = NULL;
304         priv->empty_view  = NULL;
305         priv->progress_widgets  = NULL;
306         priv->progress_bar = NULL;
307         priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
308         priv->style  = MODEST_MAIN_WINDOW_STYLE_SPLIT;
309         priv->contents_style  = -1; /* invalid contents style. We need this to select it for the first time */
310         priv->merge_ids = NULL;
311         priv->optimized_view  = FALSE;
312         priv->send_receive_in_progress  = FALSE;
313         priv->progress_bar_timeout = 0;
314         priv->queue_changed_handler_uid = 0;
315 }
316
317 static void
318 modest_main_window_finalize (GObject *obj)
319 {
320         ModestMainWindowPrivate *priv;
321
322         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
323
324         modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
325
326         g_slist_free (priv->progress_widgets);
327
328         g_byte_array_free (priv->merge_ids, TRUE);
329
330         if (priv->progress_bar_timeout > 0) {
331                 g_source_remove (priv->progress_bar_timeout);
332                 priv->progress_bar_timeout = 0;
333         }
334
335         /* Disconnect signal handlers */
336         if (priv->queue_changed_handler_uid)
337                 g_signal_handler_disconnect (modest_runtime_get_mail_operation_queue (),
338                                              priv->queue_changed_handler_uid);
339
340         G_OBJECT_CLASS(parent_class)->finalize (obj);
341 }
342
343 GtkWidget*
344 modest_main_window_get_child_widget (ModestMainWindow *self,
345                                      ModestWidgetType widget_type)
346 {
347         ModestMainWindowPrivate *priv;
348         GtkWidget *widget;
349         
350         g_return_val_if_fail (self, NULL);
351         g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_WIDGET_TYPE_NUM,
352                               NULL);
353         
354         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
355
356         switch (widget_type) {
357         case MODEST_WIDGET_TYPE_HEADER_VIEW:
358                 widget = (GtkWidget*)priv->header_view; break;
359         case MODEST_WIDGET_TYPE_FOLDER_VIEW:
360                 widget = (GtkWidget*)priv->folder_view; break;
361         default:
362                 return NULL;
363         }
364
365         return widget ? GTK_WIDGET(widget) : NULL;
366 }
367
368
369 static void
370 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
371 {
372         ModestConf *conf;
373         ModestMainWindowPrivate *priv;
374
375         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
376
377         conf = modest_runtime_get_conf ();
378
379         modest_widget_memory_restore (conf, G_OBJECT(self),
380                                       MODEST_CONF_MAIN_WINDOW_KEY);
381
382         modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
383                                       MODEST_CONF_HEADER_VIEW_KEY);
384
385         if (do_folder_view_too)
386                 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
387                                       MODEST_CONF_FOLDER_VIEW_KEY);
388
389         modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
390                                       MODEST_CONF_MAIN_PANED_KEY);
391
392         /* We need to force a redraw here in order to get the right
393            position of the horizontal paned separator */
394         gtk_widget_show (GTK_WIDGET (self));
395 }
396
397
398 static void
399 save_state (ModestWindow *window)
400 {
401         ModestConf *conf;
402         ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
403         ModestMainWindowPrivate *priv;
404                 
405         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
406         conf = modest_runtime_get_conf ();
407         
408         modest_widget_memory_save (conf,G_OBJECT(self), 
409                                    MODEST_CONF_MAIN_WINDOW_KEY);
410         modest_widget_memory_save (conf, G_OBJECT(priv->main_paned), 
411                                    MODEST_CONF_MAIN_PANED_KEY);
412         //      modest_widget_memory_save (conf, G_OBJECT(priv->header_view), 
413         //                         MODEST_CONF_HEADER_VIEW_KEY);
414         modest_widget_memory_save (conf, G_OBJECT(priv->folder_view), 
415                                    MODEST_CONF_FOLDER_VIEW_KEY);
416 }
417
418 static void
419 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
420 {
421         if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
422                 gtk_scrolled_window_add_with_viewport
423                         (GTK_SCROLLED_WINDOW(win), widget);
424         else
425                 gtk_container_add (GTK_CONTAINER(win),
426                                    widget);
427 }
428
429
430 static gboolean
431 on_delete_event (GtkWidget *widget, GdkEvent  *event, ModestMainWindow *self)
432 {
433         modest_window_save_state (MODEST_WINDOW(self));
434         return FALSE;
435 }
436
437 typedef struct
438 {
439         ModestMainWindow *self;
440         TnySendQueue *queue;
441         TnyHeader *header;
442 } OnResponseInfo;
443
444 static void
445 on_response (GtkDialog *dialog, gint arg1, gpointer user_data)
446 {
447         OnResponseInfo *info = (OnResponseInfo *) user_data;
448         ModestMainWindow *self = info->self;
449         TnyHeader *header = info->header;
450         TnySendQueue *queue = info->queue;
451
452         if (arg1 == GTK_RESPONSE_YES) {
453                 TnyFolder *outbox = tny_send_queue_get_outbox (queue);
454                 tny_folder_remove_msg (outbox, header, NULL);
455                 tny_folder_sync (outbox, TRUE, NULL);
456                 g_object_unref (outbox);
457         }
458
459         g_object_unref (queue);
460         g_object_unref (header);
461         g_object_unref (self);
462
463         gtk_widget_destroy (GTK_WIDGET (dialog));
464         g_slice_free (OnResponseInfo, info);
465 }
466
467
468 static void
469 on_sendqueue_error_happened (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, GError *err, ModestMainWindow *user_data)
470 {
471         if (header) {
472                 gchar *str = g_strdup_printf ("%s. Do you want to remove the message (%s)?",
473                         err->message, tny_header_get_subject (header));
474                 OnResponseInfo *info = g_slice_new (OnResponseInfo);
475                 GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (user_data), 0,
476                         GTK_MESSAGE_ERROR, GTK_BUTTONS_YES_NO, str);
477                 g_free (str);
478                 info->queue = g_object_ref (self);
479                 info->self = g_object_ref (user_data);
480                 info->header = g_object_ref (header);
481                 g_signal_connect (G_OBJECT (dialog), "response",
482                         G_CALLBACK (on_response), info);
483                 gtk_widget_show_all (dialog);
484         }
485 }
486
487 typedef struct {
488         TnySendQueue *queue;
489         guint signal;
490 } QueueErrorSignal;
491
492 static void
493 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
494 {
495         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
496
497         GList *oerrsignals = priv->queue_err_signals;
498         while (oerrsignals) {
499                 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
500                 g_signal_handler_disconnect (esignal->queue, esignal->signal);
501                 g_slice_free (QueueErrorSignal, esignal);
502                 oerrsignals = g_list_next (oerrsignals);
503         }
504         g_list_free (priv->queue_err_signals);
505         priv->queue_err_signals = NULL;
506 }
507
508 static void
509 on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self)
510 {
511         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
512
513         /* When going online, do the equivalent of pressing the send/receive button, 
514          * as per the specification:
515          * (without the check for >0 accounts, though that is not specified): */
516
517         TnyDevice *device = tny_account_store_get_device (store);
518
519         /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (priv->folder_view), store); */
520         
521         /* Check that we are really online.
522          * This signal should not be emitted when we are not connected, 
523          * but it seems to happen sometimes: */
524          if (!tny_device_is_online (device))
525                 return;
526                 
527         const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
528         printf ("DEBUG: %s: connection id=%s\n", __FUNCTION__, iap_id);
529         
530         /* Stop the existing send queues: */
531         modest_runtime_remove_all_send_queues ();
532         
533         /* Create the send queues again, using the appropriate transport accounts 
534          * for this new connection.
535          * This could be the first time that they are created if this is the first 
536          * connection. */
537         /* TODO: Does this really destroy the TnySendQueues and their threads
538          * We do not want 2 TnySendQueues to exist with the same underlying 
539          * outbox directory. */
540
541         modest_main_window_cleanup_queue_error_signals (self);
542
543         GSList *account_names = modest_account_mgr_account_names (
544                 modest_runtime_get_account_mgr(), 
545                 TRUE /* enabled accounts only */);
546         GSList *iter = account_names;
547         while (iter) {
548                 const gchar *account_name = (const gchar*)(iter->data);
549                         if (account_name) {
550                         TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT (
551                                 modest_tny_account_store_get_transport_account_for_open_connection
552                                                  (modest_runtime_get_account_store(), account_name));
553                         if (account) {
554                                 /* Q: Is this the first location where the send-queues are requested? */
555                                 QueueErrorSignal *esignal = g_slice_new (QueueErrorSignal);
556                                 printf ("debug: %s:\n  Transport account for %s: %s\n", __FUNCTION__, account_name, 
557                                         tny_account_get_id(TNY_ACCOUNT(account)));
558                                 esignal->queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (account));
559                                 esignal->signal = g_signal_connect (G_OBJECT (esignal->queue), "error-happened",
560                                         G_CALLBACK (on_sendqueue_error_happened), self);
561                                 priv->queue_err_signals = g_list_prepend (priv->queue_err_signals, esignal);
562                         }
563                 }
564                 
565                 iter = g_slist_next (iter);
566         }
567
568         modest_account_mgr_free_account_names (account_names);
569         account_names = NULL;
570         
571         modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self));
572 }
573
574 static void
575 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
576 {
577         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
578
579         /* Update dimmed */     
580         modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");  
581 }
582
583 static void
584 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
585 {
586         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
587
588         /* Update visibility */
589
590         /* Update dimmed */     
591         modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");  
592 }
593
594 static void
595 connect_signals (ModestMainWindow *self)
596 {       
597         ModestWindowPrivate *parent_priv;
598         ModestMainWindowPrivate *priv;
599         GtkWidget *menu;
600         
601         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
602         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
603
604         /* folder view */
605         g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
606                           G_CALLBACK(on_inner_widgets_key_pressed), self);
607         g_signal_connect (G_OBJECT(priv->folder_view), "folder_selection_changed",
608                           G_CALLBACK(modest_ui_actions_on_folder_selection_changed), self);
609         g_signal_connect (G_OBJECT(priv->folder_view), "folder-display-name-changed",
610                           G_CALLBACK(modest_ui_actions_on_folder_display_name_changed), self);
611
612         /* Folder view CSM */
613         menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
614         gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
615         g_signal_connect (G_OBJECT(priv->folder_view), "tap-and-hold",
616                           G_CALLBACK(_folder_view_csm_menu_activated),
617                           self);
618         /* header view */
619         g_signal_connect (G_OBJECT(priv->header_view), "header_selected",
620                           G_CALLBACK(modest_ui_actions_on_header_selected), self);
621         g_signal_connect (G_OBJECT(priv->header_view), "header_activated",
622                           G_CALLBACK(modest_ui_actions_on_header_activated), self);
623         g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
624                           G_CALLBACK(modest_ui_actions_on_item_not_found), self);
625         g_signal_connect (G_OBJECT(priv->header_view), "key-press-event",
626                           G_CALLBACK(on_inner_widgets_key_pressed), self);
627         g_signal_connect (G_OBJECT(priv->header_view), "msg_count_changed",
628                           G_CALLBACK(_on_msg_count_changed), self);
629
630         /* Header view CSM */
631         menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
632         gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
633         g_signal_connect (G_OBJECT(priv->header_view), "tap-and-hold",
634                           G_CALLBACK(_header_view_csm_menu_activated),
635                           self);
636         
637         /* window */
638         g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self);
639         g_signal_connect (G_OBJECT (self), "window-state-event",
640                           G_CALLBACK (modest_main_window_window_state_event),
641                           NULL);
642         
643         /* Mail Operation Queue */
644         priv->queue_changed_handler_uid = 
645                 g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
646                                   "queue-changed", G_CALLBACK (on_queue_changed), self);
647
648         /* Track changes in the device name */
649         g_signal_connect (G_OBJECT(modest_runtime_get_conf ()),
650                           "key_changed", G_CALLBACK (on_configuration_key_changed), 
651                           self);
652
653         /* Track account changes. We need to refresh the toolbar */
654         g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
655                           "account_update", G_CALLBACK (on_account_update),
656                           self);
657
658         /* Account store */
659         g_signal_connect (G_OBJECT (modest_runtime_get_account_store()), 
660                           "password_requested",
661                           G_CALLBACK (modest_ui_actions_on_password_requested), self);
662                           
663         /* Device */
664         g_signal_connect (G_OBJECT(modest_runtime_get_account_store()), 
665                           "connecting-finished",
666                           G_CALLBACK(on_account_store_connecting_finished), self);
667 }
668
669 #if 0
670 /** Idle handler, to send/receive at startup .*/
671 gboolean
672 sync_accounts_cb (ModestMainWindow *win)
673 {
674         modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
675         return FALSE; /* Do not call this idle handler again. */
676 }
677 #endif
678
679 static void on_hildon_program_is_topmost_notify(GObject *self,
680         GParamSpec *propert_param, gpointer user_data)
681 {
682         HildonProgram *app = HILDON_PROGRAM (self);
683         
684         /*
685         ModestWindow* self = MODEST_WINDOW(user_data);
686         */
687         
688         /* Note that use of hildon_program_set_can_hibernate() 
689          * is generally referred to as "setting the killable flag", 
690          * though hibernation does not seem equal to death.
691          * murrayc */
692                  
693         if (hildon_program_get_is_topmost (app)) {
694                 /* Prevent hibernation when the progam comes to the foreground,
695                  * because hibernation should only happen when the application 
696                  * is in the background: */
697                 hildon_program_set_can_hibernate (app, FALSE);
698         } else {
699                 /* Allow hibernation if the program has gone to the background: */
700                 
701                 /* However, prevent hibernation while the settings are being changed: */
702                 const gboolean hibernation_prevented = 
703                         modest_window_mgr_get_hibernation_is_prevented (
704         modest_runtime_get_window_mgr ()); 
705         
706                 if (hibernation_prevented)
707                         hildon_program_set_can_hibernate (app, FALSE);
708                 else {
709                         /* Allow hibernation, after saving the state: */
710                         modest_osso_save_state();
711                         hildon_program_set_can_hibernate (app, TRUE);
712                 }
713         }
714         
715 }
716
717 static void
718 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
719 {
720         GtkWidget *folder_win = (GtkWidget *) user_data;
721         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
722         
723         priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
724         wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
725 /*      wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
726
727         gtk_widget_show (GTK_WIDGET (priv->folder_view));
728
729         /* Connect signals */
730         connect_signals ((ModestMainWindow*)self);
731
732         /* Set account store */
733         tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
734                                                   TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
735
736         /* Load previous osso state, for instance if we are being restored from 
737          * hibernation:  */
738         modest_osso_load_state ();
739
740         /* Restore window & widget settings */
741         
742         restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
743
744         /* Check if accounts exist and show the account wizard if not */
745         gboolean accounts_exist = 
746                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
747
748         if (!accounts_exist) {
749                 /* This is necessary to have the main window shown behind the dialog 
750                 It's an ugly hack... jschmid */
751                 gtk_widget_show_all(GTK_WIDGET(self));
752                 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
753         } else {
754                 GSList *accounts;
755                 GtkAction *send_receive_all;
756                 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
757                 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
758                 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager, 
759                                                               "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
760                 gtk_action_set_visible (send_receive_all, g_slist_length (accounts));
761                 modest_account_mgr_free_account_names (accounts);
762         }
763
764
765 }
766
767 ModestWindow *
768 modest_main_window_new (void)
769 {
770         ModestMainWindow *self = NULL;  
771         ModestMainWindowPrivate *priv = NULL;
772         ModestWindowPrivate *parent_priv = NULL;
773         GtkWidget *folder_win = NULL;
774         ModestDimmingRulesGroup *menu_rules_group = NULL;
775         ModestDimmingRulesGroup *toolbar_rules_group = NULL;
776         GtkActionGroup *action_group = NULL;
777         GError *error = NULL;
778         ModestConf *conf = NULL;
779         GtkAction *action = NULL;
780
781         self  = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
782         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
783         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
784
785         parent_priv->ui_manager = gtk_ui_manager_new();
786         parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
787
788         action_group = gtk_action_group_new ("ModestMainWindowActions");
789         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
790
791         menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules");
792         toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules");
793
794         /* Add common actions */
795         gtk_action_group_add_actions (action_group,
796                                       modest_action_entries,
797                                       G_N_ELEMENTS (modest_action_entries),
798                                       self);
799
800         gtk_action_group_add_actions (action_group,
801                                       modest_folder_view_action_entries,
802                                       G_N_ELEMENTS (modest_folder_view_action_entries),
803                                       self);
804
805         gtk_action_group_add_actions (action_group,
806                                       modest_header_view_action_entries,
807                                       G_N_ELEMENTS (modest_header_view_action_entries),
808                                       self);
809
810         gtk_action_group_add_toggle_actions (action_group,
811                                              modest_toggle_action_entries,
812                                              G_N_ELEMENTS (modest_toggle_action_entries),
813                                              self);
814
815         gtk_action_group_add_toggle_actions (action_group,
816                                              modest_main_window_toggle_action_entries,
817                                              G_N_ELEMENTS (modest_main_window_toggle_action_entries),
818                                              self);
819
820         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
821         g_object_unref (action_group);
822
823         /* Load the UI definition */
824         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
825                                          MODEST_UIDIR "modest-main-window-ui.xml", &error);
826         if (error != NULL) {
827                 g_warning ("Could not merge modest-ui.xml: %s", error->message);
828                 g_error_free (error);
829                 error = NULL;
830         }
831
832         /* Add common dimming rules */
833         modest_dimming_rules_group_add_rules (menu_rules_group, 
834                                               modest_main_window_menu_dimming_entries,
835                                               G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
836                                               self);
837         modest_dimming_rules_group_add_rules (toolbar_rules_group, 
838                                               modest_main_window_toolbar_dimming_entries,
839                                               G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
840                                               self);
841
842         /* Insert dimming rules group for this window */
843         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
844         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
845         g_object_unref (menu_rules_group);
846         g_object_unref (toolbar_rules_group);
847         
848         /* Add accelerators */
849         gtk_window_add_accel_group (GTK_WINDOW (self), 
850                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
851
852         /* Menubar. Update the state of some toggles */
853         parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
854         conf = modest_runtime_get_conf ();
855         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
856                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
857         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
858                                       modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
859         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
860                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
861         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
862                                       modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
863         hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
864
865         /* Get device name */
866         modest_maemo_utils_get_device_name ();
867
868         /* header view */
869         priv->header_view =
870                 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
871         if (!priv->header_view)
872                 g_printerr ("modest: cannot instantiate header view\n");
873         modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
874         modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
875                                       MODEST_CONF_HEADER_VIEW_KEY);
876
877         /* Empty view */ 
878         priv->empty_view = create_empty_view ();
879                  
880         /* Create scrolled windows */
881         folder_win = gtk_scrolled_window_new (NULL, NULL);
882         priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
883         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
884                                         GTK_POLICY_NEVER,
885                                         GTK_POLICY_AUTOMATIC);
886         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
887                                         GTK_POLICY_NEVER,
888                                         GTK_POLICY_AUTOMATIC);
889
890         /* paned */
891         priv->main_paned = gtk_hpaned_new ();
892         gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
893         gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
894         gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
895
896         /* putting it all together... */
897         priv->main_vbox = gtk_vbox_new (FALSE, 6);
898         gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
899
900         gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
901         
902         HildonProgram *app = hildon_program_get_instance ();
903         hildon_program_add_window (app, HILDON_WINDOW (self));
904         
905         g_signal_connect (G_OBJECT(app), "notify::is-topmost",
906                 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
907
908         g_signal_connect (G_OBJECT(self), "show",
909                           G_CALLBACK (modest_main_window_on_show), folder_win);
910                 
911
912         restore_settings (MODEST_MAIN_WINDOW(self), FALSE);
913
914         return MODEST_WINDOW(self);
915 }
916
917 gboolean 
918 modest_main_window_close_all (ModestMainWindow *self)
919 {
920         GtkWidget *note;
921         GtkResponseType response;
922
923         /* Create the confirmation dialog MSG-NOT308 */
924         note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
925                                                          _("emev_nc_close_windows"),
926                                                          _("mcen_bd_yes"), GTK_RESPONSE_YES,
927                                                          _("mcen_bd_no"), GTK_RESPONSE_NO,
928                                                          NULL);
929
930         response = gtk_dialog_run (GTK_DIALOG (note));
931         gtk_widget_destroy (GTK_WIDGET (note));
932
933         if (response == GTK_RESPONSE_YES)
934                 return TRUE;
935         else
936                 return FALSE;
937 }
938
939
940 void 
941 modest_main_window_set_style (ModestMainWindow *self, 
942                               ModestMainWindowStyle style)
943 {
944         ModestMainWindowPrivate *priv;
945         ModestWindowPrivate *parent_priv;
946         GtkAction *action;
947
948         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
949
950         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
951         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
952
953         /* no change -> nothing to do */
954         if (priv->style == style)
955                 return;
956
957         /* Get toggle button */
958         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarToggleView");
959
960         priv->style = style;
961         switch (style) {
962         case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
963                 /* Remove main paned */
964                 g_object_ref (priv->main_paned);
965                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
966
967                 /* Reparent the contents widget to the main vbox */
968                 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
969
970                 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
971                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
972                 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
973
974                 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
975                         TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
976                         TnyIterator *iterator = tny_list_create_iterator (selection);
977                         TnyHeader *header;
978                         tny_iterator_first (iterator);
979                         header = TNY_HEADER (tny_iterator_get_current (iterator));
980                         if (tny_header_get_subject (header))
981                                 gtk_window_set_title (GTK_WINDOW(self), tny_header_get_subject (header));
982                         else
983                                 gtk_window_set_title (GTK_WINDOW (self), _("mail_va_no_subject"));
984                         g_object_unref (header);
985                         g_object_unref (iterator);
986                         g_object_unref (selection);
987                 }
988
989                 break;
990         case MODEST_MAIN_WINDOW_STYLE_SPLIT:
991                 /* Remove header view */
992                 g_object_ref (priv->contents_widget);
993                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
994
995                 /* Reparent the main paned */
996                 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
997                 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
998
999                 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1000                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
1001                 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1002
1003                 break;
1004         default:
1005                 g_return_if_reached ();
1006         }
1007
1008         /* Let header view grab the focus if it's being shown */
1009         if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1010                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1011         else 
1012                 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1013
1014         /* Show changes */
1015         gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1016 }
1017
1018 ModestMainWindowStyle
1019 modest_main_window_get_style (ModestMainWindow *self)
1020 {
1021         ModestMainWindowPrivate *priv;
1022
1023         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1024
1025         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1026         return priv->style;
1027 }
1028
1029
1030
1031 static gboolean
1032 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1033 {
1034         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1035                 ModestWindowPrivate *parent_priv;
1036                 ModestWindowMgr *mgr;
1037                 gboolean is_fullscreen;
1038                 GtkAction *fs_toggle_action;
1039                 gboolean active;
1040                 
1041                 mgr = modest_runtime_get_window_mgr ();
1042                 
1043                 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1044
1045                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1046                 
1047                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1048                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1049                 if (is_fullscreen != active) {
1050                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1051                 }
1052         }
1053
1054         return FALSE;
1055
1056 }
1057
1058 static void
1059 set_homogeneous (GtkWidget *widget,
1060                  gpointer data)
1061 {
1062         gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1063         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1064 }
1065
1066 static void 
1067 modest_main_window_show_toolbar (ModestWindow *self,
1068                                  gboolean show_toolbar)
1069 {
1070         ModestMainWindowPrivate *priv = NULL;
1071         ModestWindowPrivate *parent_priv = NULL;        
1072         GtkWidget *reply_button = NULL, *menu = NULL;
1073         GtkWidget *placeholder = NULL;
1074         gint insert_index;
1075
1076         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1077         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1078         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1079
1080         /* Set optimized view status */
1081         priv->optimized_view = !show_toolbar;
1082
1083         if (!parent_priv->toolbar) {
1084                 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
1085                                                                   "/ToolBar");
1086
1087                 /* Set homogeneous toolbar */
1088                 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar), 
1089                                        set_homogeneous, NULL);
1090         
1091                 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1092                 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1093                 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1094                 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1095                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1096                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1097                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1098                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1099
1100                 /* Add ProgressBar (Transfer toolbar) */ 
1101                 priv->progress_bar = modest_progress_bar_widget_new ();
1102                 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1103                 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1104                 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1105                 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1106                 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1107                 
1108                 /* Connect cancel 'clicked' signal to abort progress mode */
1109                 g_signal_connect(priv->cancel_toolitem, "clicked",
1110                                  G_CALLBACK(cancel_progressbar),
1111                                  self);
1112                 
1113                 /* Add it to the observers list */
1114                 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1115
1116                 /* Add to window */
1117                 hildon_window_add_toolbar (HILDON_WINDOW (self), 
1118                                            GTK_TOOLBAR (parent_priv->toolbar));
1119
1120                 /* Set reply button tap and hold menu */
1121                 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
1122                                                           "/ToolBar/ToolbarMessageReply");
1123                 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1124                                                   "/ToolbarReplyCSM");
1125                 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1126
1127                 /* Set send & receive button tap and hold menu */
1128                 on_account_update (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
1129                                    NULL, self);
1130         }
1131
1132         if (show_toolbar) {
1133                 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */ 
1134                 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1135                 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1136
1137                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1138                 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1139         } else
1140                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1141
1142 }
1143
1144 static gint
1145 compare_display_names (ModestAccountData *a,
1146                        ModestAccountData *b)
1147 {
1148         return strcmp (a->display_name, b->display_name);
1149 }
1150
1151 static void 
1152 on_account_update (TnyAccountStore *account_store, 
1153                    const gchar *account_name,
1154                    gpointer user_data)
1155 {
1156         GSList *account_names, *iter, *accounts;
1157         ModestMainWindow *self;
1158         ModestMainWindowPrivate *priv;
1159         ModestWindowPrivate *parent_priv;
1160         ModestAccountMgr *mgr;
1161         gint i, num_accounts;                                   
1162         GtkActionGroup *action_group;
1163         GList *groups;
1164         gchar *default_account;
1165         GtkWidget *send_receive_button, *item;
1166         GtkAction *send_receive_all = NULL;
1167                 
1168         self = MODEST_MAIN_WINDOW (user_data);
1169         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1170         parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1171
1172         /* Get enabled account IDs */
1173         mgr = modest_runtime_get_account_mgr ();
1174         account_names = modest_account_mgr_account_names (mgr, TRUE);
1175         iter = account_names;
1176         accounts = NULL;
1177
1178         while (iter) {
1179                 ModestAccountData *account_data = 
1180                         modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
1181                 accounts = g_slist_prepend (accounts, account_data);
1182
1183                 iter = iter->next;
1184         }
1185         modest_account_mgr_free_account_names (account_names);
1186         account_names = NULL;
1187
1188         /* Order the list of accounts by its display name */
1189         accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
1190         num_accounts = g_slist_length (accounts);
1191
1192         send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager, 
1193                                                       "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1194         gtk_action_set_visible (send_receive_all, num_accounts > 1);
1195
1196         /* Delete old send&receive popup items. We can not just do a
1197            menu_detach because it does not work well with
1198            tap_and_hold */
1199         if (priv->accounts_popup)
1200                 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup), 
1201                                        (GtkCallback) gtk_widget_destroy, NULL);
1202
1203         /* Delete old entries in the View menu. Do not free groups, it
1204            belongs to Gtk+ */
1205         groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
1206         while (groups) {
1207                 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
1208                              gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
1209                         gtk_ui_manager_remove_action_group (parent_priv->ui_manager, 
1210                                                             GTK_ACTION_GROUP (groups->data));
1211                         groups = NULL;
1212                         /* Remove uis */
1213                         if (priv->merge_ids) {
1214                                 for (i = 0; i < priv->merge_ids->len; i++)
1215                                         gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
1216                                 g_byte_array_free (priv->merge_ids, TRUE);
1217                         }
1218                         /* We need to call this in order to ensure
1219                            that the new actions are added in the right
1220                            order (alphabetical */
1221                         gtk_ui_manager_ensure_update (parent_priv->ui_manager);
1222                 } else 
1223                         groups = g_list_next (groups);
1224         }
1225         priv->merge_ids = g_byte_array_sized_new (num_accounts);
1226
1227         /* Get send receive button */
1228         send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1229                                                           "/ToolBar/ToolbarSendReceive");
1230
1231         /* Create the menu */
1232         if (num_accounts > 1) {
1233                 if (!priv->accounts_popup)
1234                         priv->accounts_popup = gtk_menu_new ();
1235                 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
1236                 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1237                 g_signal_connect (G_OBJECT (item), 
1238                                   "activate", 
1239                                   G_CALLBACK (on_send_receive_csm_activated),
1240                                   NULL);
1241                 item = gtk_separator_menu_item_new ();
1242                 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1243         }
1244
1245         /* Create a new action group */
1246         default_account = modest_account_mgr_get_default_account (mgr);
1247         action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
1248         for (i = 0; i < num_accounts; i++) {
1249                 gchar *display_name = NULL;
1250                 
1251                 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1252
1253                 /* Create display name. The default account is shown differently */
1254                 if (default_account && account_data->account_name && 
1255                         !(strcmp (default_account, account_data->account_name) == 0)) {
1256                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"), 
1257                                                         account_data->display_name);
1258                 }
1259                 else {
1260                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"), 
1261                                                         account_data->display_name);
1262                 }
1263
1264                 /* Create action and add it to the action group. The
1265                    action name must be the account name, this way we
1266                    could know in the handlers the account to show */
1267                 if(account_data->account_name) {
1268                         gchar* item_name, *refresh_action_name;
1269                         guint8 merge_id;
1270                         GtkAction *view_account_action, *refresh_account_action;
1271
1272                         view_account_action = gtk_action_new (account_data->account_name,
1273                                                               display_name, NULL, NULL);
1274                         gtk_action_group_add_action (action_group, view_account_action);
1275
1276                         /* Add ui from account data. We allow 2^9-1 account
1277                            changes in a single execution because we're
1278                            downcasting the guint to a guint8 in order to use a
1279                            GByteArray, it should be enough */
1280                         item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1281                         merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1282                         priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1283                         gtk_ui_manager_add_ui (parent_priv->ui_manager,
1284                                                merge_id,
1285                                                "/MenuBar/ViewMenu/ViewMenuAdditions",
1286                                                item_name,
1287                                                account_data->account_name,
1288                                                GTK_UI_MANAGER_MENUITEM,
1289                                                FALSE);
1290         
1291                         /* Connect the action signal "activate" */
1292                         g_signal_connect (G_OBJECT (view_account_action),
1293                                           "activate",
1294                                           G_CALLBACK (on_show_account_action_activated),
1295                                           self);
1296
1297                         /* Create the items for the Tools->Send&Receive submenu */
1298                         refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
1299                         refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name, 
1300                                                                  display_name, NULL, NULL);
1301                         gtk_action_group_add_action (action_group, refresh_account_action);
1302
1303                         merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1304                         priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1305                         gtk_ui_manager_add_ui (parent_priv->ui_manager, 
1306                                                merge_id,
1307                                                "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
1308                                                item_name,
1309                                                refresh_action_name,
1310                                                GTK_UI_MANAGER_MENUITEM,
1311                                                FALSE);
1312                         g_free (refresh_action_name);
1313
1314                         g_signal_connect_data (G_OBJECT (refresh_account_action), 
1315                                                "activate", 
1316                                                G_CALLBACK (on_refresh_account_action_activated), 
1317                                                g_strdup (account_data->account_name),
1318                                                (GClosureNotify) g_free,
1319                                                0);
1320
1321                         /* Create item and add it to the send&receive
1322                            CSM. If there is only one account then
1323                            it'll be no menu */
1324                         if (priv->accounts_popup) {
1325                                 item = gtk_menu_item_new_with_label (display_name);
1326                                 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1327                                 g_signal_connect_data (G_OBJECT (item), 
1328                                                        "activate", 
1329                                                        G_CALLBACK (on_send_receive_csm_activated),
1330                                                        g_strdup (account_data->account_name),
1331                                                        (GClosureNotify) g_free,
1332                                                        0);
1333                         }
1334                         g_free (item_name);
1335                 }
1336
1337                 /* Frees */
1338                 g_free (display_name);
1339                 modest_account_mgr_free_account_data (mgr, account_data);
1340         }
1341         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1342
1343         if (priv->accounts_popup) {
1344                 /* Mandatory in order to view the menu contents */
1345                 gtk_widget_show_all (priv->accounts_popup);
1346
1347                 /* Setup tap_and_hold just if was not done before*/
1348                 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1349                         gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1350         }
1351
1352         /* Frees */
1353         g_slist_free (accounts);
1354         g_free (default_account);
1355 }
1356
1357 /* 
1358  * This function manages the key events used to navigate between
1359  * header and folder views (when the window is in split view)
1360  *
1361  * FROM         KEY        ACTION
1362  * -------------------------------------------------
1363  * HeaderView   GDK_Left   Move focus to folder view
1364  * FolderView   GDK_Right  Move focus to header view
1365  *
1366  * There is no need to scroll to selected row, the widgets will be the
1367  * responsibles of doing that (probably managing the focus-in event
1368  */
1369 static gboolean 
1370 on_inner_widgets_key_pressed (GtkWidget *widget,
1371                               GdkEventKey *event,
1372                               gpointer user_data)
1373 {
1374         ModestMainWindowPrivate *priv;
1375
1376         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1377
1378         /* Do nothing if we're in SIMPLE style */
1379         if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1380                 return FALSE;
1381
1382         if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1383                 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1384         else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1385                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1386
1387         return FALSE;
1388 }
1389
1390 static void
1391 set_alignment (GtkWidget *widget,
1392                gpointer data)
1393 {
1394         gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1395         gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1396 }
1397
1398 static GtkWidget *
1399 create_empty_view (void)
1400 {
1401         GtkLabel *label = NULL;
1402         GtkWidget *align = NULL;
1403
1404         align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1405         label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1406         gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);      
1407         gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1408
1409         return GTK_WIDGET(align);
1410 }
1411
1412 static GtkWidget *
1413 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1414 {
1415         /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1416         
1417         GtkWidget *vbox;
1418         GtkWidget *label_w;
1419         gchar *label;
1420         gchar *gray_color_markup;
1421
1422         vbox = gtk_vbox_new (FALSE, 0);
1423
1424         /* Obtain the secondary text color. We need a realized widget, that's why 
1425            we get styled_widget from outside */
1426 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1427         GdkColor color;
1428         gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1429         gray_color_markup = modest_text_utils_get_color_string (&color);
1430 #else
1431         // gray_color_markup is freed below
1432         gray_color_markup = g_strdup ("#BBBBBB");
1433 #endif  
1434         /* Account description: */
1435         
1436         if (modest_tny_account_is_virtual_local_folders (account)
1437                 || (modest_tny_account_is_memory_card_account (account))) {
1438                 gchar *tmp;
1439                 /* Local folders: */
1440         
1441                 /* Get device name */
1442                 gchar *device_name = NULL;
1443                 if (modest_tny_account_is_virtual_local_folders (account))
1444                         device_name = modest_conf_get_string (modest_runtime_get_conf(),
1445                                                       MODEST_CONF_DEVICE_NAME, NULL);
1446                 else
1447                         device_name = g_strdup (tny_account_get_name (account));
1448                                                       
1449                 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), ""); //TODO: Why the ""?
1450                 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1451                                                  gray_color_markup, tmp, device_name);
1452                 g_free (tmp);
1453                 label_w = gtk_label_new (NULL);
1454                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1455                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1456                 g_free (device_name);
1457                 g_free (label);
1458         } else {
1459                 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1460                         gtk_box_pack_start (GTK_BOX (vbox), 
1461                                 gtk_label_new (tny_account_get_name (account)), 
1462                                 FALSE, FALSE, 0);
1463                 } else {
1464                         /* Other accounts, such as IMAP and POP: */
1465                         
1466                         GString *proto;
1467                         gchar *tmp;
1468         
1469                         /* Put proto in uppercase */
1470                         proto = g_string_new (tny_account_get_proto (account));
1471                         proto = g_string_ascii_up (proto);
1472                         
1473                         /* note: mcen_fi_localroot_description is something like "%s account"
1474                          * however, we should display "%s account: %s"... therefore, ugly tmp */
1475                         tmp   = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1476                         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1477                                                          gray_color_markup, tmp, tny_account_get_name (account));
1478                         g_free (tmp);
1479
1480                         label_w = gtk_label_new (NULL);
1481                         gtk_label_set_markup (GTK_LABEL (label_w), label);
1482                         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1483                         g_string_free (proto, TRUE);
1484                         g_free (label);
1485                 }
1486         }
1487
1488         /* Message count */
1489         TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1490         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", 
1491                                          gray_color_markup, _("mcen_fi_rootfolder_messages"), 
1492                                          modest_tny_folder_store_get_message_count (folder_store));
1493         label_w = gtk_label_new (NULL);
1494         gtk_label_set_markup (GTK_LABEL (label_w), label);
1495         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1496         g_free (label);
1497
1498         /* Folder count */
1499         label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d", 
1500                                          gray_color_markup, 
1501                                          _("mcen_fi_rootfolder_folders"), 
1502                                          modest_tny_folder_store_get_folder_count (folder_store));
1503         label_w = gtk_label_new (NULL);
1504         gtk_label_set_markup (GTK_LABEL (label_w), label);
1505         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1506         g_free (label);
1507
1508         /* Size / Date */
1509         if (modest_tny_account_is_virtual_local_folders (account)
1510                 || modest_tny_account_is_memory_card_account (account)) {
1511                 /* FIXME: format size */
1512                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", 
1513                                                  gray_color_markup, _("mcen_fi_rootfolder_size"), 
1514                                                  modest_tny_folder_store_get_local_size (folder_store));
1515                 label_w = gtk_label_new (NULL);
1516                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1517                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1518                 g_free (label);
1519         } else if (TNY_IS_ACCOUNT(folder_store)) {
1520                 TnyAccount *account = TNY_ACCOUNT(folder_store);
1521                 
1522                 time_t last_updated;
1523                 gchar *last_updated_string;
1524                 /* Get last updated from configuration */
1525                 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (), 
1526                                                           tny_account_get_id (account), 
1527                                                           MODEST_ACCOUNT_LAST_UPDATED, 
1528                                                           TRUE);
1529                 if (last_updated > 0) 
1530                         last_updated_string = modest_text_utils_get_display_date(last_updated);
1531                 else
1532                         last_updated_string = g_strdup (_("mcen_va_never"));
1533
1534                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1535                                                  gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1536                 label_w = gtk_label_new (NULL);
1537                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1538                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1539                 g_free (last_updated_string);
1540                 g_free (label);
1541         }
1542
1543         g_free (gray_color_markup);
1544
1545         /* Set alignment */
1546         gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1547
1548         return vbox;
1549 }
1550
1551 gboolean
1552 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1553 {
1554         ModestMainWindowPrivate *priv = NULL;
1555         
1556         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1557
1558         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1559
1560         return priv->send_receive_in_progress;
1561 }
1562
1563 void 
1564 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1565 {
1566         GtkAction *action = NULL;
1567         GtkWidget *widget = NULL;
1568         ModestMainWindowPrivate *priv = NULL;
1569                 
1570         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1571         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1572         
1573         priv->send_receive_in_progress  = TRUE;
1574
1575         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1576         gtk_action_set_sensitive (action, FALSE);
1577 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1578 /*      gtk_action_set_sensitive (action, FALSE); */
1579         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1580         gtk_widget_set_sensitive (widget, FALSE);
1581
1582
1583 void 
1584 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1585 {
1586         GtkAction *action = NULL;
1587         GtkWidget *widget = NULL;
1588         ModestMainWindowPrivate *priv = NULL;
1589                 
1590         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1591         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1592
1593         priv->send_receive_in_progress  = FALSE;
1594
1595         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1596         gtk_action_set_sensitive (action, TRUE);
1597 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu");     */
1598 /*      gtk_action_set_sensitive (action, TRUE); */
1599         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1600         gtk_widget_set_sensitive (widget, TRUE);
1601
1602
1603
1604 static void
1605 _on_msg_count_changed (ModestHeaderView *header_view,
1606                        TnyFolder *folder,
1607                        TnyFolderChange *change,
1608                        ModestMainWindow *main_window)
1609 {
1610         printf ("DEBUG: %s\n", __FUNCTION__);
1611         gboolean folder_empty = FALSE;
1612         TnyFolderChangeChanged changed;
1613         
1614         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1615         g_return_if_fail (TNY_IS_FOLDER(folder));
1616         g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1617         
1618         changed = tny_folder_change_get_changed (change);
1619         
1620         /* If something changes */
1621         if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1622                 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);     
1623         else
1624                 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1625         
1626         printf ("DEBUG: %s: folder_empty=%d\n", __FUNCTION__, folder_empty);
1627
1628         /* Set contents style of headers view */
1629         if (folder_empty)  {
1630                 modest_main_window_set_contents_style (main_window,
1631                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1632         }
1633         else {
1634                 modest_main_window_set_contents_style (main_window,
1635                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1636         }       
1637 }
1638
1639 void 
1640 modest_main_window_set_contents_style (ModestMainWindow *self, 
1641                                        ModestMainWindowContentsStyle style)
1642 {
1643         ModestMainWindowPrivate *priv;
1644
1645         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1646
1647         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1648
1649         /* We allow to set the same content style than the previously
1650            set if there are details, because it could happen when we're
1651            selecting different accounts consecutively */
1652         if ((priv->contents_style == style) &&
1653             (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1654                 return;
1655
1656         /* Remove previous child. Delete it if it was an account
1657            details widget */
1658         GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1659         if (content) {
1660                 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1661                         g_object_ref (content);
1662                 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1663                         g_object_ref (priv->empty_view);
1664                         gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1665                 }
1666                 
1667                 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1668         }
1669
1670         priv->contents_style = style;
1671
1672         switch (priv->contents_style) {
1673         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1674                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1675                 break;
1676         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1677         {
1678                 TnyFolderStore *selected_folderstore = 
1679                         modest_folder_view_get_selected (priv->folder_view);
1680                 if (TNY_IS_ACCOUNT (selected_folderstore)) {    
1681                   priv->details_widget = create_details_widget (GTK_WIDGET (self),
1682                                                                 TNY_ACCOUNT (selected_folderstore));
1683
1684                         wrap_in_scrolled_window (priv->contents_widget, 
1685                                          priv->details_widget);
1686                 }
1687                 g_object_unref (selected_folderstore);
1688                 break;
1689         }
1690         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1691                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1692                 break;
1693         default:
1694                 g_return_if_reached ();
1695         }
1696
1697         /* Show */
1698         gtk_widget_show_all (priv->contents_widget);
1699 }
1700
1701 ModestMainWindowContentsStyle
1702 modest_main_window_get_contents_style (ModestMainWindow *self)
1703 {
1704         ModestMainWindowPrivate *priv;
1705
1706         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1707
1708         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1709         return priv->contents_style;
1710 }
1711
1712
1713 static void 
1714 on_configuration_key_changed (ModestConf* conf, 
1715                               const gchar *key, 
1716                               ModestConfEvent event, 
1717                               ModestMainWindow *self)
1718 {
1719         ModestMainWindowPrivate *priv;
1720         TnyAccount *account;
1721
1722         if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1723                 return;
1724
1725         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1726
1727         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1728                 return;
1729
1730         account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1731         if (TNY_IS_ACCOUNT (account) &&
1732             !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1733                 GList *children;
1734                 GtkLabel *label;
1735                 const gchar *device_name;
1736                 gchar *new_text;
1737                 
1738                 /* Get label */
1739                 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1740                 label = GTK_LABEL (children->data);
1741                 
1742                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1743                                                       MODEST_CONF_DEVICE_NAME, NULL);
1744                 
1745                 new_text = g_strdup_printf ("%s: %s",
1746                                             _("mcen_fi_localroot_description"),
1747                                             device_name);
1748                 
1749                 gtk_label_set_text (label, new_text);
1750                 gtk_widget_show (GTK_WIDGET (label));
1751                 
1752                 g_free (new_text);
1753                 g_list_free (children);
1754         }
1755         g_object_unref (account);
1756 }
1757
1758 static gboolean
1759 set_toolbar_transfer_mode (ModestMainWindow *self)
1760 {
1761         ModestMainWindowPrivate *priv = NULL;
1762         
1763         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1764
1765         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1766
1767         set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1768         
1769         if (priv->progress_bar_timeout > 0) {
1770                 g_source_remove (priv->progress_bar_timeout);
1771                 priv->progress_bar_timeout = 0;
1772         }
1773
1774         return FALSE;
1775 }
1776
1777 static void 
1778 set_toolbar_mode (ModestMainWindow *self, 
1779                   ModestToolBarModes mode)
1780 {
1781         ModestWindowPrivate *parent_priv = NULL;
1782         ModestMainWindowPrivate *priv = NULL;
1783         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1784         
1785         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1786
1787         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1788         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1789
1790         /* In case this was called before the toolbar exists: */
1791         if (!(parent_priv->toolbar))
1792                 return;
1793
1794         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
1795         
1796         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1797         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1798         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1799
1800         /* Sets current toolbar mode */
1801         priv->current_toolbar_mode = mode;
1802
1803         /* Show and hide toolbar items */
1804         switch (mode) {
1805         case TOOLBAR_MODE_NORMAL:
1806                 if (sort_action)
1807                         gtk_action_set_visible (sort_action, TRUE);
1808                 if (refresh_action)
1809                         gtk_action_set_visible (refresh_action, TRUE);
1810                 if (priv->progress_toolitem) {
1811                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1812                         gtk_widget_hide (priv->progress_toolitem);
1813                 }
1814                 if (priv->progress_bar)
1815                         gtk_widget_hide (priv->progress_bar);
1816                 
1817                 if (cancel_action)
1818                         gtk_action_set_visible (cancel_action, FALSE);
1819 /*              if (priv->sort_toolitem) */
1820 /*                      gtk_widget_show (priv->sort_toolitem); */
1821                 
1822 /*              if (priv->refresh_toolitem) */
1823 /*                      gtk_widget_show (priv->refresh_toolitem); */
1824                         
1825 /*              if (priv->progress_toolitem) */
1826 /*                      gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE); */
1827 /*              if (priv->progress_bar) */
1828 /*                      gtk_widget_hide (priv->progress_bar); */
1829                         
1830 /*              if (priv->cancel_toolitem) */
1831 /*                      gtk_widget_hide (priv->cancel_toolitem); */
1832
1833                 /* Hide toolbar if optimized view is enabled */
1834                 if (priv->optimized_view)
1835                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1836                 break;
1837         case TOOLBAR_MODE_TRANSFER:
1838                 if (sort_action)
1839                         gtk_action_set_visible (sort_action, FALSE);
1840                 if (refresh_action)
1841                         gtk_action_set_visible (refresh_action, FALSE);
1842                 if (cancel_action)
1843                         gtk_action_set_visible (cancel_action, TRUE);
1844                 if (priv->progress_toolitem) {
1845                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1846                         gtk_widget_show (priv->progress_toolitem);
1847                 }
1848                 if (priv->progress_bar)
1849                         gtk_widget_show (priv->progress_bar);
1850
1851 /*              if (priv->sort_toolitem) */
1852 /*                      gtk_widget_hide (priv->sort_toolitem); */
1853                 
1854 /*              if (priv->refresh_toolitem) */
1855 /*                      gtk_widget_hide (priv->refresh_toolitem); */
1856                 
1857 /*              if (priv->progress_toolitem) */
1858 /*                      gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE); */
1859 /*              if (priv->progress_bar) */
1860 /*                      gtk_widget_show (priv->progress_bar); */
1861                         
1862 /*              if (priv->cancel_toolitem) */
1863 /*                      gtk_widget_show (priv->cancel_toolitem); */
1864
1865                 /* Show toolbar if it's hiden (optimized view ) */
1866                 if (priv->optimized_view)
1867                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1868                 break;
1869         default:
1870                 g_return_if_reached ();
1871         }
1872 }
1873
1874 static void
1875 cancel_progressbar (GtkToolButton *toolbutton,
1876                     ModestMainWindow *self)
1877 {
1878         GSList *tmp;
1879         ModestMainWindowPrivate *priv;
1880         
1881         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1882
1883         /* Get operation observers and cancel its current operation */
1884         tmp = priv->progress_widgets;
1885         while (tmp) {
1886                 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
1887                 tmp=g_slist_next(tmp);
1888         }
1889 }
1890
1891 static gboolean
1892 observers_empty (ModestMainWindow *self)
1893 {
1894         GSList *tmp = NULL;
1895         ModestMainWindowPrivate *priv;
1896         gboolean is_empty = TRUE;
1897         guint pending_ops = 0;
1898  
1899         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1900         tmp = priv->progress_widgets;
1901
1902         /* Check all observers */
1903         while (tmp && is_empty)  {
1904                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1905                 is_empty = pending_ops == 0;
1906                 
1907                 tmp = g_slist_next(tmp);
1908         }
1909         
1910         return is_empty;
1911 }
1912
1913 static void
1914 on_queue_changed (ModestMailOperationQueue *queue,
1915                   ModestMailOperation *mail_op,
1916                   ModestMailOperationQueueNotification type,
1917                   ModestMainWindow *self)
1918 {
1919         ModestMainWindowPrivate *priv;
1920         ModestMailOperationTypeOperation op_type;
1921         ModestToolBarModes mode;
1922         GSList *tmp;
1923         gboolean mode_changed = FALSE;
1924 /*      ModestMailOperationStatus status; */
1925
1926         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1927         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1928                
1929         /* Get toolbar mode from operation id*/
1930         op_type = modest_mail_operation_get_type_operation (mail_op);
1931         switch (op_type) {
1932         case MODEST_MAIL_OPERATION_TYPE_SEND:
1933         case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1934         case MODEST_MAIL_OPERATION_TYPE_OPEN:
1935                 mode = TOOLBAR_MODE_TRANSFER;
1936                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
1937                         mode_changed = TRUE;
1938                 break;
1939         default:
1940                 mode = TOOLBAR_MODE_NORMAL;
1941                 
1942         }
1943                 
1944                        
1945         /* Add operation observers and change toolbar if neccessary*/
1946         tmp = priv->progress_widgets;
1947         switch (type) {
1948         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
1949                 if (mode == TOOLBAR_MODE_TRANSFER) {
1950                         if (mode_changed)
1951                                 set_toolbar_transfer_mode(self);                    
1952                         while (tmp) {
1953                                 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1954                                                                       mail_op);
1955                                 tmp = g_slist_next (tmp);
1956                         }
1957                 }
1958                 break;
1959         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
1960                 /* Change toolbar mode */
1961                 if (mode == TOOLBAR_MODE_TRANSFER) {                    
1962                         while (tmp) {
1963                                 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1964                                                                          mail_op);
1965                                 tmp = g_slist_next (tmp);
1966                         }
1967                         
1968                         /* If no more operations are being observed, NORMAL mode is enabled again */
1969                         if (observers_empty (self)) {
1970                                 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
1971                                 
1972                         }
1973                 }
1974
1975                 break;
1976         }       
1977
1978 }
1979
1980 static void 
1981 on_show_account_action_activated  (GtkAction *action,
1982                                    gpointer user_data)
1983 {
1984         ModestAccountData *acc_data;
1985         ModestMainWindow *self;
1986         ModestMainWindowPrivate *priv;
1987         ModestAccountMgr *mgr;
1988         const gchar *acc_name;
1989
1990         self = MODEST_MAIN_WINDOW (user_data);
1991         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1992
1993         /* Get account data */
1994         acc_name = gtk_action_get_name (action);
1995         mgr = modest_runtime_get_account_mgr ();
1996         acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
1997
1998         /* Set the new visible & active account */
1999         if (acc_data->store_account) { 
2000                 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2001                                                                              acc_data->store_account->account_name);
2002                 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2003         }
2004
2005         /* Free */
2006         modest_account_mgr_free_account_data (mgr, acc_data);
2007 }
2008
2009 static void
2010 refresh_account (const gchar *account_name)
2011 {
2012         ModestWindow *win;
2013
2014         win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2015
2016         /* If account_name == NULL, we must update all (option All) */
2017         if (!account_name)
2018                 modest_ui_actions_do_send_receive_all (win);
2019         else
2020                 modest_ui_actions_do_send_receive (account_name, win);
2021         
2022 }
2023
2024 static void 
2025 on_refresh_account_action_activated  (GtkAction *action,
2026                                       gpointer user_data)
2027 {
2028         refresh_account ((const gchar*) user_data);
2029 }
2030
2031 static void
2032 on_send_receive_csm_activated (GtkMenuItem *item,
2033                                gpointer user_data)
2034 {
2035         refresh_account ((const gchar*) user_data);
2036 }
2037
2038 static gboolean
2039 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2040 {
2041         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2042
2043         hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2044         return FALSE;
2045
2046 }