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