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