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