af388a7ea47a4de07a7ab5ceee1b3481f47f33fc
[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         ModestConf *conf;
389         ModestMainWindowPrivate *priv;
390
391         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
392
393         conf = modest_runtime_get_conf ();
394
395         modest_widget_memory_restore (conf, G_OBJECT(self),
396                                       MODEST_CONF_MAIN_WINDOW_KEY);
397
398         modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
399                                       MODEST_CONF_HEADER_VIEW_KEY);
400
401         if (do_folder_view_too)
402                 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
403                                       MODEST_CONF_FOLDER_VIEW_KEY);
404
405         modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
406                                       MODEST_CONF_MAIN_PANED_KEY);
407
408         /* We need to force a redraw here in order to get the right
409            position of the horizontal paned separator */
410         gtk_widget_show (GTK_WIDGET (self));
411 }
412
413
414 static void
415 save_state (ModestWindow *window)
416 {
417         ModestConf *conf;
418         ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
419         ModestMainWindowPrivate *priv;
420                 
421         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
422         conf = modest_runtime_get_conf ();
423         
424         modest_widget_memory_save (conf,G_OBJECT(self), 
425                                    MODEST_CONF_MAIN_WINDOW_KEY);
426         modest_widget_memory_save (conf, G_OBJECT(priv->main_paned), 
427                                    MODEST_CONF_MAIN_PANED_KEY);
428         //      modest_widget_memory_save (conf, G_OBJECT(priv->header_view), 
429         //                         MODEST_CONF_HEADER_VIEW_KEY);
430         modest_widget_memory_save (conf, G_OBJECT(priv->folder_view), 
431                                    MODEST_CONF_FOLDER_VIEW_KEY);
432 }
433
434 static void
435 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
436 {
437         if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
438                 gtk_scrolled_window_add_with_viewport
439                         (GTK_SCROLLED_WINDOW(win), widget);
440         else
441                 gtk_container_add (GTK_CONTAINER(win),
442                                    widget);
443 }
444
445
446 /* static gboolean */
447 /* on_delete_event (GtkWidget *widget, GdkEvent  *event, ModestMainWindow *self) */
448 /* { */
449 /*      modest_window_save_state (MODEST_WINDOW(self)); */
450 /*      return FALSE; */
451 /* } */
452
453 static void
454 on_sendqueue_error_happened (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, GError *err, ModestMainWindow *user_data)
455 {
456         if (err) {
457                 printf ("DEBUG: %s: err->code=%d, err->message=%s\n", __FUNCTION__, err->code, err->message);
458
459                 if (err->code == TNY_ACCOUNT_ERROR_TRY_CONNECT_USER_CANCEL)
460                         /* Don't show waste the user's time by showing him a dialog telling him
461                          * that he has just cancelled something: */
462                         return;
463         }
464
465         /* Get the server name: */
466         const gchar* server_name = NULL;
467         
468         TnyCamelTransportAccount* server_account = tny_camel_send_queue_get_transport_account (
469                 TNY_CAMEL_SEND_QUEUE (self));
470         if (server_account) {
471                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
472                         
473                 g_object_unref (server_account);
474                 server_account = NULL;
475         }
476         
477         if (!server_name)
478                 server_name = _("Unknown Server");      
479
480         /* Show the appropriate message text for the GError: */
481         gchar *message = NULL;
482         if (err) {
483                 switch (err->code) {
484                         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
485                                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
486                                 break;
487                         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
488                                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
489                                 break;
490                         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
491                                 /* TODO: This logical ID seems more suitable for a wrong username or password than for a 
492                                  * wrong authentication method. The user is unlikely to guess at the real cause.
493                                  */
494                                 message = g_strdup_printf (_("eemev_ni_ui_smtp_authentication_fail_error"), server_name);
495                                 break;
496                         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
497                         default:
498                                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
499                                 break;
500                 }
501         } else {
502                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
503         }
504         
505         modest_maemo_show_information_note_and_forget (GTK_WINDOW (user_data), message);
506         g_free (message);
507         
508         /* TODO: Offer to remove the message, to avoid messages in future? */
509         /*
510         TnyFolder *outbox = tny_send_queue_get_outbox (queue);
511         tny_folder_remove_msg (outbox, header, NULL);
512         tny_folder_sync (outbox, TRUE, NULL);
513         g_object_unref (outbox);
514         */
515 }
516
517 typedef struct {
518         TnySendQueue *queue;
519         guint signal;
520 } QueueErrorSignal;
521
522 static void
523 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
524 {
525         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
526
527         GList *oerrsignals = priv->queue_err_signals;
528         while (oerrsignals) {
529                 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
530                 g_signal_handler_disconnect (esignal->queue, esignal->signal);
531                 g_slice_free (QueueErrorSignal, esignal);
532                 oerrsignals = g_list_next (oerrsignals);
533         }
534         g_list_free (priv->queue_err_signals);
535         priv->queue_err_signals = NULL;
536 }
537
538 static void
539 on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self)
540 {
541         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
542
543         /* When going online, do the equivalent of pressing the send/receive button, 
544          * as per the specification:
545          * (without the check for >0 accounts, though that is not specified): */
546
547         TnyDevice *device = tny_account_store_get_device (store);
548
549         /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (priv->folder_view), store); */
550         
551         /* Check that we are really online.
552          * This signal should not be emitted when we are not connected, 
553          * but it seems to happen sometimes: */
554          if (!tny_device_is_online (device))
555                 return;
556                 
557         const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
558         printf ("DEBUG: %s: connection id=%s\n", __FUNCTION__, iap_id);
559         
560         /* Stop the existing send queues: */
561         modest_runtime_remove_all_send_queues ();
562         
563         /* Create the send queues again, using the appropriate transport accounts 
564          * for this new connection.
565          * This could be the first time that they are created if this is the first 
566          * connection. */
567         /* TODO: Does this really destroy the TnySendQueues and their threads
568          * We do not want 2 TnySendQueues to exist with the same underlying 
569          * outbox directory. */
570
571         modest_main_window_cleanup_queue_error_signals (self);
572
573         GSList *account_names = modest_account_mgr_account_names (
574                 modest_runtime_get_account_mgr(), 
575                 TRUE /* enabled accounts only */);
576         GSList *iter = account_names;
577         while (iter) {
578                 const gchar *account_name = (const gchar*)(iter->data);
579                         if (account_name) {
580                         TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT (
581                                 modest_tny_account_store_get_transport_account_for_open_connection
582                                                  (modest_runtime_get_account_store(), account_name));
583                         if (account) {
584                                 /* Q: Is this the first location where the send-queues are requested? */
585                                 QueueErrorSignal *esignal = g_slice_new (QueueErrorSignal);
586                                 printf ("debug: %s:\n  Transport account for %s: %s\n", __FUNCTION__, account_name, 
587                                         tny_account_get_id(TNY_ACCOUNT(account)));
588                                 esignal->queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (account));
589                                 esignal->signal = g_signal_connect (G_OBJECT (esignal->queue), "error-happened",
590                                         G_CALLBACK (on_sendqueue_error_happened), self);
591                                 priv->queue_err_signals = g_list_prepend (priv->queue_err_signals, esignal);
592                         }
593                 }
594                 
595                 iter = g_slist_next (iter);
596         }
597
598         modest_account_mgr_free_account_names (account_names);
599         account_names = NULL;
600         
601         modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self));
602 }
603
604 static void
605 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
606 {
607         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
608
609         /* Update dimmed */     
610         modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");  
611 }
612
613 static void
614 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
615 {
616         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
617
618         /* Update visibility */
619
620         /* Update dimmed */     
621         modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");  
622 }
623
624 static void
625 connect_signals (ModestMainWindow *self)
626 {       
627         ModestWindowPrivate *parent_priv;
628         ModestMainWindowPrivate *priv;
629         GtkWidget *menu;
630         
631         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
632         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
633
634         /* folder view */
635         g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
636                           G_CALLBACK(on_inner_widgets_key_pressed), self);
637         g_signal_connect (G_OBJECT(priv->folder_view), "folder_selection_changed",
638                           G_CALLBACK(modest_main_window_on_folder_selection_changed), self);
639         g_signal_connect (G_OBJECT(priv->folder_view), "folder-display-name-changed",
640                           G_CALLBACK(modest_ui_actions_on_folder_display_name_changed), self);
641         g_signal_connect (G_OBJECT (priv->folder_view), "focus-in-event", 
642                           G_CALLBACK (on_folder_view_focus_in), self);
643
644         /* Folder view CSM */
645         menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
646         gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
647         g_signal_connect (G_OBJECT(priv->folder_view), "tap-and-hold",
648                           G_CALLBACK(_folder_view_csm_menu_activated),
649                           self);
650         /* header view */
651         g_signal_connect (G_OBJECT(priv->header_view), "header_selected",
652                           G_CALLBACK(modest_ui_actions_on_header_selected), self);
653         g_signal_connect (G_OBJECT(priv->header_view), "header_activated",
654                           G_CALLBACK(modest_ui_actions_on_header_activated), self);
655         g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
656                           G_CALLBACK(modest_ui_actions_on_item_not_found), self);
657         g_signal_connect (G_OBJECT(priv->header_view), "key-press-event",
658                           G_CALLBACK(on_inner_widgets_key_pressed), self);
659         g_signal_connect (G_OBJECT(priv->header_view), "msg_count_changed",
660                           G_CALLBACK(_on_msg_count_changed), self);
661         g_signal_connect (G_OBJECT (priv->header_view), "focus-in-event",
662                           G_CALLBACK (on_header_view_focus_in), self);
663
664         /* Header view CSM */
665         menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
666         gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
667         g_signal_connect (G_OBJECT(priv->header_view), "tap-and-hold",
668                           G_CALLBACK(_header_view_csm_menu_activated),
669                           self);
670         
671         /* window */
672 /*      g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self); */
673         g_signal_connect (G_OBJECT (self), "window-state-event",
674                           G_CALLBACK (modest_main_window_window_state_event),
675                           NULL);
676         
677         /* Mail Operation Queue */
678         priv->queue_changed_handler_uid = 
679                 g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
680                                   "queue-changed", G_CALLBACK (on_queue_changed), self);
681
682         /* Track changes in the device name */
683         g_signal_connect (G_OBJECT(modest_runtime_get_conf ()),
684                           "key_changed", G_CALLBACK (on_configuration_key_changed), 
685                           self);
686
687         /* Track account changes. We need to refresh the toolbar */
688         g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
689                           "account_update", G_CALLBACK (on_account_update),
690                           self);
691
692         /* Account store */
693         g_signal_connect (G_OBJECT (modest_runtime_get_account_store()), 
694                           "password_requested",
695                           G_CALLBACK (modest_ui_actions_on_password_requested), self);
696                           
697         /* Device */
698         g_signal_connect (G_OBJECT(modest_runtime_get_account_store()), 
699                           "connecting-finished",
700                           G_CALLBACK(on_account_store_connecting_finished), self);
701 }
702
703 #if 0
704 /** Idle handler, to send/receive at startup .*/
705 gboolean
706 sync_accounts_cb (ModestMainWindow *win)
707 {
708         modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
709         return FALSE; /* Do not call this idle handler again. */
710 }
711 #endif
712
713 static void on_hildon_program_is_topmost_notify(GObject *self,
714         GParamSpec *propert_param, gpointer user_data)
715 {
716         HildonProgram *app = HILDON_PROGRAM (self);
717         
718         /*
719         ModestWindow* self = MODEST_WINDOW(user_data);
720         */
721         
722         /* Note that use of hildon_program_set_can_hibernate() 
723          * is generally referred to as "setting the killable flag", 
724          * though hibernation does not seem equal to death.
725          * murrayc */
726                  
727         if (hildon_program_get_is_topmost (app)) {
728                 /* Prevent hibernation when the progam comes to the foreground,
729                  * because hibernation should only happen when the application 
730                  * is in the background: */
731                 hildon_program_set_can_hibernate (app, FALSE);
732         } else {
733                 /* Allow hibernation if the program has gone to the background: */
734                 
735                 /* However, prevent hibernation while the settings are being changed: */
736                 const gboolean hibernation_prevented = 
737                         modest_window_mgr_get_hibernation_is_prevented (
738         modest_runtime_get_window_mgr ()); 
739         
740                 if (hibernation_prevented)
741                         hildon_program_set_can_hibernate (app, FALSE);
742                 else {
743                         /* Allow hibernation, after saving the state: */
744                         modest_osso_save_state();
745                         hildon_program_set_can_hibernate (app, TRUE);
746                 }
747         }
748         
749 }
750
751 static void
752 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
753 {
754         GtkWidget *folder_win = (GtkWidget *) user_data;
755         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
756         
757         priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
758         wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
759 /*      wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
760
761         gtk_widget_show (GTK_WIDGET (priv->folder_view));
762
763         /* Connect signals */
764         connect_signals ((ModestMainWindow*)self);
765
766         /* Set account store */
767         tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
768                                                   TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
769
770         /* Load previous osso state, for instance if we are being restored from 
771          * hibernation:  */
772         modest_osso_load_state ();
773
774         /* Restore window & widget settings */
775         
776         restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
777
778         /* Check if accounts exist and show the account wizard if not */
779         gboolean accounts_exist = 
780                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
781
782         if (!accounts_exist) {
783                 /* This is necessary to have the main window shown behind the dialog 
784                 It's an ugly hack... jschmid */
785                 gtk_widget_show_all(GTK_WIDGET(self));
786                 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
787         } else {
788                 GSList *accounts;
789                 GtkAction *send_receive_all;
790                 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
791                 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
792                 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager, 
793                                                               "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
794                 gtk_action_set_visible (send_receive_all, g_slist_length (accounts));
795                 modest_account_mgr_free_account_names (accounts);
796         }
797
798
799 }
800
801 ModestWindow *
802 modest_main_window_new (void)
803 {
804         ModestMainWindow *self = NULL;  
805         ModestMainWindowPrivate *priv = NULL;
806         ModestWindowPrivate *parent_priv = NULL;
807         GtkWidget *folder_win = NULL;
808         ModestDimmingRulesGroup *menu_rules_group = NULL;
809         ModestDimmingRulesGroup *toolbar_rules_group = NULL;
810         GtkActionGroup *action_group = NULL;
811         GError *error = NULL;
812         ModestConf *conf = NULL;
813         GtkAction *action = NULL;
814         GdkPixbuf *window_icon;
815         
816         self  = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
817         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
818         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
819
820         parent_priv->ui_manager = gtk_ui_manager_new();
821         parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
822
823         action_group = gtk_action_group_new ("ModestMainWindowActions");
824         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
825
826         menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
827         toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
828
829         /* Add common actions */
830         gtk_action_group_add_actions (action_group,
831                                       modest_action_entries,
832                                       G_N_ELEMENTS (modest_action_entries),
833                                       self);
834
835         gtk_action_group_add_actions (action_group,
836                                       modest_folder_view_action_entries,
837                                       G_N_ELEMENTS (modest_folder_view_action_entries),
838                                       self);
839
840         gtk_action_group_add_actions (action_group,
841                                       modest_header_view_action_entries,
842                                       G_N_ELEMENTS (modest_header_view_action_entries),
843                                       self);
844
845         gtk_action_group_add_toggle_actions (action_group,
846                                              modest_toggle_action_entries,
847                                              G_N_ELEMENTS (modest_toggle_action_entries),
848                                              self);
849
850         gtk_action_group_add_toggle_actions (action_group,
851                                              modest_main_window_toggle_action_entries,
852                                              G_N_ELEMENTS (modest_main_window_toggle_action_entries),
853                                              self);
854
855         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
856         g_object_unref (action_group);
857
858         /* Load the UI definition */
859         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
860                                          MODEST_UIDIR "modest-main-window-ui.xml", &error);
861         if (error != NULL) {
862                 g_warning ("Could not merge modest-ui.xml: %s", error->message);
863                 g_error_free (error);
864                 error = NULL;
865         }
866
867         /* Add common dimming rules */
868         modest_dimming_rules_group_add_rules (menu_rules_group, 
869                                               modest_main_window_menu_dimming_entries,
870                                               G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
871                                               self);
872         modest_dimming_rules_group_add_rules (toolbar_rules_group, 
873                                               modest_main_window_toolbar_dimming_entries,
874                                               G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
875                                               self);
876
877         /* Insert dimming rules group for this window */
878         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
879         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
880         g_object_unref (menu_rules_group);
881         g_object_unref (toolbar_rules_group);
882         
883         /* Add accelerators */
884         gtk_window_add_accel_group (GTK_WINDOW (self), 
885                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
886
887         /* Menubar. Update the state of some toggles */
888         parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
889         conf = modest_runtime_get_conf ();
890         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
891                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
892         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
893                                       modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
894         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
895                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
896         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
897                                       modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
898         hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
899
900         /* Get device name */
901         modest_maemo_utils_get_device_name ();
902
903         /* header view */
904         priv->header_view =
905                 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
906         if (!priv->header_view)
907                 g_printerr ("modest: cannot instantiate header view\n");
908         modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
909         modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
910                                       MODEST_CONF_HEADER_VIEW_KEY);
911
912         /* Other style properties of header view */
913         g_object_set (G_OBJECT (priv->header_view), 
914                       "rules-hint", FALSE,
915                       NULL);
916
917         /* Empty view */ 
918         priv->empty_view = create_empty_view ();
919                  
920         /* Create scrolled windows */
921         folder_win = gtk_scrolled_window_new (NULL, NULL);
922         priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
923         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
924                                         GTK_POLICY_NEVER,
925                                         GTK_POLICY_AUTOMATIC);
926         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
927                                         GTK_POLICY_NEVER,
928                                         GTK_POLICY_AUTOMATIC);
929
930         /* paned */
931         priv->main_paned = gtk_hpaned_new ();
932         gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
933         gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
934         gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
935
936         /* putting it all together... */
937         priv->main_vbox = gtk_vbox_new (FALSE, 6);
938         gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
939
940         gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
941         
942         HildonProgram *app = hildon_program_get_instance ();
943         hildon_program_add_window (app, HILDON_WINDOW (self));
944         
945         g_signal_connect (G_OBJECT(app), "notify::is-topmost",
946                 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
947
948         g_signal_connect (G_OBJECT(self), "show",
949                           G_CALLBACK (modest_main_window_on_show), folder_win);
950                 
951         /* Set window icon */
952         window_icon = modest_platform_get_icon (MODEST_APP_ICON);
953         if (window_icon) {
954                 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
955                 g_object_unref (window_icon);
956         }
957
958         restore_settings (MODEST_MAIN_WINDOW(self), FALSE);
959
960         return MODEST_WINDOW(self);
961 }
962
963 gboolean 
964 modest_main_window_close_all (ModestMainWindow *self)
965 {
966         GtkWidget *note;
967         GtkResponseType response;
968
969         /* Create the confirmation dialog MSG-NOT308 */
970         note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
971                                                          _("emev_nc_close_windows"),
972                                                          _("mcen_bd_yes"), GTK_RESPONSE_YES,
973                                                          _("mcen_bd_no"), GTK_RESPONSE_NO,
974                                                          NULL);
975
976         response = gtk_dialog_run (GTK_DIALOG (note));
977         gtk_widget_destroy (GTK_WIDGET (note));
978
979         if (response == GTK_RESPONSE_YES)
980                 return TRUE;
981         else
982                 return FALSE;
983 }
984
985
986 void 
987 modest_main_window_set_style (ModestMainWindow *self, 
988                               ModestMainWindowStyle style)
989 {
990         ModestMainWindowPrivate *priv;
991         ModestWindowPrivate *parent_priv;
992         GtkAction *action;
993         gboolean active;
994
995         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
996
997         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
998         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
999
1000         /* no change -> nothing to do */
1001         if (priv->style == style)
1002                 return;
1003
1004        /* Get toggle button and update the state if needed. This will
1005           happen only when the set_style is not invoked from the UI,
1006           for example when it's called from widget memory */
1007        action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1008        active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1009        if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1010            (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1011                g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1012                gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1013                g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1014        }
1015
1016         priv->style = style;
1017         switch (style) {
1018         case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1019                 /* Remove main paned */
1020                 g_object_ref (priv->main_paned);
1021                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1022
1023                 /* Reparent the contents widget to the main vbox */
1024                 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1025
1026                 if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
1027                         TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
1028                         TnyIterator *iterator = tny_list_create_iterator (selection);
1029                         TnyHeader *header;
1030                         tny_iterator_first (iterator);
1031                         header = TNY_HEADER (tny_iterator_get_current (iterator));
1032                         if (tny_header_get_subject (header))
1033                                 gtk_window_set_title (GTK_WINDOW(self), tny_header_get_subject (header));
1034                         else
1035                                 gtk_window_set_title (GTK_WINDOW (self), _("mail_va_no_subject"));
1036                         g_object_unref (header);
1037                         g_object_unref (iterator);
1038                         g_object_unref (selection);
1039                 }
1040
1041                 break;
1042         case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1043                 /* Remove header view */
1044                 g_object_ref (priv->contents_widget);
1045                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1046
1047                 /* Reparent the main paned */
1048                 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1049                 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1050
1051                 break;
1052         default:
1053                 g_return_if_reached ();
1054         }
1055
1056         /* Let header view grab the focus if it's being shown */
1057         if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1058                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1059         else 
1060                 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1061
1062         /* Show changes */
1063         gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1064 }
1065
1066 ModestMainWindowStyle
1067 modest_main_window_get_style (ModestMainWindow *self)
1068 {
1069         ModestMainWindowPrivate *priv;
1070
1071         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1072
1073         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1074         return priv->style;
1075 }
1076
1077
1078
1079 static gboolean
1080 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1081 {
1082         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1083                 ModestWindowPrivate *parent_priv;
1084                 ModestWindowMgr *mgr;
1085                 gboolean is_fullscreen;
1086                 GtkAction *fs_toggle_action;
1087                 gboolean active;
1088                 
1089                 mgr = modest_runtime_get_window_mgr ();
1090                 
1091                 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1092
1093                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1094                 
1095                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1096                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1097                 if (is_fullscreen != active) {
1098                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1099                 }
1100         }
1101
1102         return FALSE;
1103
1104 }
1105
1106 static void
1107 set_homogeneous (GtkWidget *widget,
1108                  gpointer data)
1109 {
1110         gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1111         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1112 }
1113
1114 static void 
1115 modest_main_window_show_toolbar (ModestWindow *self,
1116                                  gboolean show_toolbar)
1117 {
1118         ModestMainWindowPrivate *priv = NULL;
1119         ModestWindowPrivate *parent_priv = NULL;        
1120         GtkWidget *reply_button = NULL, *menu = NULL;
1121         GtkWidget *placeholder = NULL;
1122         gint insert_index;
1123
1124         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1125         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1126         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1127
1128         /* Set optimized view status */
1129         priv->optimized_view = !show_toolbar;
1130
1131         if (!parent_priv->toolbar) {
1132                 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
1133                                                                   "/ToolBar");
1134
1135                 /* Set homogeneous toolbar */
1136                 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar), 
1137                                        set_homogeneous, NULL);
1138         
1139                 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1140                 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1141                 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1142                 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1143                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1144                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1145                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1146                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1147
1148                 /* Add ProgressBar (Transfer toolbar) */ 
1149                 priv->progress_bar = modest_progress_bar_widget_new ();
1150                 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1151                 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1152                 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1153                 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1154                 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1155                 
1156                 /* Connect cancel 'clicked' signal to abort progress mode */
1157                 g_signal_connect(priv->cancel_toolitem, "clicked",
1158                                  G_CALLBACK(cancel_progressbar),
1159                                  self);
1160                 
1161                 /* Add it to the observers list */
1162                 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1163
1164                 /* Add to window */
1165                 hildon_window_add_toolbar (HILDON_WINDOW (self), 
1166                                            GTK_TOOLBAR (parent_priv->toolbar));
1167
1168                 /* Set reply button tap and hold menu */
1169                 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
1170                                                           "/ToolBar/ToolbarMessageReply");
1171                 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1172                                                   "/ToolbarReplyCSM");
1173                 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1174
1175                 /* Set send & receive button tap and hold menu */
1176                 on_account_update (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
1177                                    NULL, self);
1178         }
1179
1180         if (show_toolbar) {
1181                 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */ 
1182                 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1183                 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1184
1185                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1186                 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1187         } else
1188                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1189
1190 }
1191
1192 static gint
1193 compare_display_names (ModestAccountData *a,
1194                        ModestAccountData *b)
1195 {
1196         return strcmp (a->display_name, b->display_name);
1197 }
1198
1199 static void 
1200 on_account_update (TnyAccountStore *account_store, 
1201                    const gchar *account_name,
1202                    gpointer user_data)
1203 {
1204         GSList *account_names, *iter, *accounts;
1205         ModestMainWindow *self;
1206         ModestMainWindowPrivate *priv;
1207         ModestWindowPrivate *parent_priv;
1208         ModestAccountMgr *mgr;
1209         gint i, num_accounts;                                   
1210         GtkActionGroup *action_group;
1211         GList *groups;
1212         gchar *default_account;
1213         GtkWidget *send_receive_button, *item;
1214         GtkAction *send_receive_all = NULL;
1215                 
1216         self = MODEST_MAIN_WINDOW (user_data);
1217         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1218         parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1219
1220         /* Get enabled account IDs */
1221         mgr = modest_runtime_get_account_mgr ();
1222         account_names = modest_account_mgr_account_names (mgr, TRUE);
1223         iter = account_names;
1224         accounts = NULL;
1225
1226         while (iter) {
1227                 ModestAccountData *account_data = 
1228                         modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
1229                 accounts = g_slist_prepend (accounts, account_data);
1230
1231                 iter = iter->next;
1232         }
1233         modest_account_mgr_free_account_names (account_names);
1234         account_names = NULL;
1235
1236         /* Order the list of accounts by its display name */
1237         accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
1238         num_accounts = g_slist_length (accounts);
1239
1240         send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager, 
1241                                                       "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1242         gtk_action_set_visible (send_receive_all, num_accounts > 1);
1243
1244         /* Delete old send&receive popup items. We can not just do a
1245            menu_detach because it does not work well with
1246            tap_and_hold */
1247         if (priv->accounts_popup)
1248                 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup), 
1249                                        (GtkCallback) gtk_widget_destroy, NULL);
1250
1251         /* Delete old entries in the View menu. Do not free groups, it
1252            belongs to Gtk+ */
1253         groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
1254         while (groups) {
1255                 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
1256                              gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
1257                         gtk_ui_manager_remove_action_group (parent_priv->ui_manager, 
1258                                                             GTK_ACTION_GROUP (groups->data));
1259                         groups = NULL;
1260                         /* Remove uis */
1261                         if (priv->merge_ids) {
1262                                 for (i = 0; i < priv->merge_ids->len; i++)
1263                                         gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
1264                                 g_byte_array_free (priv->merge_ids, TRUE);
1265                         }
1266                         /* We need to call this in order to ensure
1267                            that the new actions are added in the right
1268                            order (alphabetical */
1269                         gtk_ui_manager_ensure_update (parent_priv->ui_manager);
1270                 } else 
1271                         groups = g_list_next (groups);
1272         }
1273         priv->merge_ids = g_byte_array_sized_new (num_accounts);
1274
1275         /* Get send receive button */
1276         send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1277                                                           "/ToolBar/ToolbarSendReceive");
1278
1279         /* Create the menu */
1280         if (num_accounts > 1) {
1281                 if (!priv->accounts_popup)
1282                         priv->accounts_popup = gtk_menu_new ();
1283                 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
1284                 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1285                 g_signal_connect (G_OBJECT (item), 
1286                                   "activate", 
1287                                   G_CALLBACK (on_send_receive_csm_activated),
1288                                   NULL);
1289                 item = gtk_separator_menu_item_new ();
1290                 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1291         }
1292
1293         /* Create a new action group */
1294         default_account = modest_account_mgr_get_default_account (mgr);
1295         action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
1296         for (i = 0; i < num_accounts; i++) {
1297                 gchar *display_name = NULL;
1298                 
1299                 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1300
1301                 /* Create display name. The UI specification specifies a different format string 
1302                  * to use for the default account, though both seem to be "%s", so 
1303                  * I don't see what the point is. murrayc. */
1304                 if (default_account && account_data->account_name && 
1305                         !(strcmp (default_account, account_data->account_name) == 0)) {
1306                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"), 
1307                                                         account_data->display_name);
1308                 }
1309                 else {
1310                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"), 
1311                                                         account_data->display_name);
1312                 }
1313
1314                 /* Create action and add it to the action group. The
1315                    action name must be the account name, this way we
1316                    could know in the handlers the account to show */
1317                 if(account_data->account_name) {
1318                         gchar* item_name, *refresh_action_name;
1319                         guint8 merge_id;
1320                         GtkAction *view_account_action, *refresh_account_action;
1321
1322                         view_account_action = gtk_action_new (account_data->account_name,
1323                                                               display_name, NULL, NULL);
1324                         gtk_action_group_add_action (action_group, view_account_action);
1325
1326                         /* Add ui from account data. We allow 2^9-1 account
1327                            changes in a single execution because we're
1328                            downcasting the guint to a guint8 in order to use a
1329                            GByteArray. It should be enough. */
1330                         item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1331                         merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1332                         priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1333                         gtk_ui_manager_add_ui (parent_priv->ui_manager,
1334                                                merge_id,
1335                                                "/MenuBar/ViewMenu/ViewMenuAdditions",
1336                                                item_name,
1337                                                account_data->account_name,
1338                                                GTK_UI_MANAGER_MENUITEM,
1339                                                FALSE);
1340         
1341                         /* Connect the action signal "activate" */
1342                         g_signal_connect (G_OBJECT (view_account_action),
1343                                           "activate",
1344                                           G_CALLBACK (on_show_account_action_activated),
1345                                           self);
1346
1347                         /* Create the items for the Tools->Send&Receive submenu */
1348                         refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
1349                         refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name, 
1350                                                                  display_name, NULL, NULL);
1351                         gtk_action_group_add_action (action_group, refresh_account_action);
1352
1353                         merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1354                         priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1355                         gtk_ui_manager_add_ui (parent_priv->ui_manager, 
1356                                                merge_id,
1357                                                "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
1358                                                item_name,
1359                                                refresh_action_name,
1360                                                GTK_UI_MANAGER_MENUITEM,
1361                                                FALSE);
1362                         g_free (refresh_action_name);
1363
1364                         g_signal_connect_data (G_OBJECT (refresh_account_action), 
1365                                                "activate", 
1366                                                G_CALLBACK (on_refresh_account_action_activated), 
1367                                                g_strdup (account_data->account_name),
1368                                                (GClosureNotify) g_free,
1369                                                0);
1370
1371                         /* Create item and add it to the send&receive
1372                            CSM. If there is only one account then
1373                            it'll be no menu */
1374                         if (priv->accounts_popup) {
1375                                 item = gtk_menu_item_new_with_label (display_name);
1376                                 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1377                                 g_signal_connect_data (G_OBJECT (item), 
1378                                                        "activate", 
1379                                                        G_CALLBACK (on_send_receive_csm_activated),
1380                                                        g_strdup (account_data->account_name),
1381                                                        (GClosureNotify) g_free,
1382                                                        0);
1383                         }
1384                         g_free (item_name);
1385                 }
1386
1387                 /* Frees */
1388                 g_free (display_name);
1389                 modest_account_mgr_free_account_data (mgr, account_data);
1390         }
1391         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1392
1393         if (priv->accounts_popup) {
1394                 /* Mandatory in order to view the menu contents */
1395                 gtk_widget_show_all (priv->accounts_popup);
1396
1397                 /* Setup tap_and_hold just if was not done before*/
1398                 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1399                         gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1400         }
1401
1402         /* Frees */
1403         g_slist_free (accounts);
1404         g_free (default_account);
1405 }
1406
1407 /* 
1408  * This function manages the key events used to navigate between
1409  * header and folder views (when the window is in split view)
1410  *
1411  * FROM         KEY        ACTION
1412  * -------------------------------------------------
1413  * HeaderView   GDK_Left   Move focus to folder view
1414  * FolderView   GDK_Right  Move focus to header view
1415  *
1416  * There is no need to scroll to selected row, the widgets will be the
1417  * responsibles of doing that (probably managing the focus-in event
1418  */
1419 static gboolean 
1420 on_inner_widgets_key_pressed (GtkWidget *widget,
1421                               GdkEventKey *event,
1422                               gpointer user_data)
1423 {
1424         ModestMainWindowPrivate *priv;
1425
1426         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1427
1428         /* Do nothing if we're in SIMPLE style */
1429         if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1430                 return FALSE;
1431
1432         if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1433                 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1434         else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1435                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1436
1437         return FALSE;
1438 }
1439
1440 static void
1441 set_alignment (GtkWidget *widget,
1442                gpointer data)
1443 {
1444         gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1445         gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1446 }
1447
1448 static GtkWidget *
1449 create_empty_view (void)
1450 {
1451         GtkLabel *label = NULL;
1452         GtkWidget *align = NULL;
1453
1454         align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1455         label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1456         gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);      
1457         gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1458
1459         return GTK_WIDGET(align);
1460 }
1461
1462 static GtkWidget *
1463 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1464 {
1465         /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1466         
1467         GtkWidget *vbox;
1468         GtkWidget *label_w;
1469         gchar *label;
1470         gchar *gray_color_markup;
1471
1472         vbox = gtk_vbox_new (FALSE, 0);
1473
1474         /* Obtain the secondary text color. We need a realized widget, that's why 
1475            we get styled_widget from outside */
1476 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1477         GdkColor color;
1478         gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1479         gray_color_markup = modest_text_utils_get_color_string (&color);
1480 #else
1481         // gray_color_markup is freed below
1482         gray_color_markup = g_strdup ("#BBBBBB");
1483 #endif  
1484         /* Account description: */
1485         
1486         if (modest_tny_account_is_virtual_local_folders (account)
1487                 || (modest_tny_account_is_memory_card_account (account))) {
1488                 gchar *tmp;
1489                 /* Local folders: */
1490         
1491                 /* Get device name */
1492                 gchar *device_name = NULL;
1493                 if (modest_tny_account_is_virtual_local_folders (account))
1494                         device_name = modest_conf_get_string (modest_runtime_get_conf(),
1495                                                       MODEST_CONF_DEVICE_NAME, NULL);
1496                 else
1497                         device_name = g_strdup (tny_account_get_name (account));
1498                                                       
1499                 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), ""); //TODO: Why the ""?
1500                 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1501                                                  gray_color_markup, tmp, device_name);
1502                 g_free (tmp);
1503                 label_w = gtk_label_new (NULL);
1504                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1505                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1506                 g_free (device_name);
1507                 g_free (label);
1508         } else {
1509                 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1510                         gtk_box_pack_start (GTK_BOX (vbox), 
1511                                 gtk_label_new (tny_account_get_name (account)), 
1512                                 FALSE, FALSE, 0);
1513                 } else {
1514                         /* Other accounts, such as IMAP and POP: */
1515                         
1516                         GString *proto;
1517                         gchar *tmp;
1518         
1519                         /* Put proto in uppercase */
1520                         proto = g_string_new (tny_account_get_proto (account));
1521                         proto = g_string_ascii_up (proto);
1522                         
1523                         /* note: mcen_fi_localroot_description is something like "%s account"
1524                          * however, we should display "%s account: %s"... therefore, ugly tmp */
1525                         tmp   = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1526                         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1527                                                          gray_color_markup, tmp, tny_account_get_name (account));
1528                         g_free (tmp);
1529
1530                         label_w = gtk_label_new (NULL);
1531                         gtk_label_set_markup (GTK_LABEL (label_w), label);
1532                         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1533                         g_string_free (proto, TRUE);
1534                         g_free (label);
1535                 }
1536         }
1537
1538         /* Message count */
1539         TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1540         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", 
1541                                          gray_color_markup, _("mcen_fi_rootfolder_messages"), 
1542                                          modest_tny_folder_store_get_message_count (folder_store));
1543         label_w = gtk_label_new (NULL);
1544         gtk_label_set_markup (GTK_LABEL (label_w), label);
1545         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1546         g_free (label);
1547
1548         /* Folder count */
1549         label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d", 
1550                                          gray_color_markup, 
1551                                          _("mcen_fi_rootfolder_folders"), 
1552                                          modest_tny_folder_store_get_folder_count (folder_store));
1553         label_w = gtk_label_new (NULL);
1554         gtk_label_set_markup (GTK_LABEL (label_w), label);
1555         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1556         g_free (label);
1557
1558         /* Size / Date */
1559         if (modest_tny_account_is_virtual_local_folders (account)
1560                 || modest_tny_account_is_memory_card_account (account)) {
1561
1562                 gchar *size = modest_text_utils_get_display_size (
1563                         modest_tny_folder_store_get_local_size (folder_store));
1564                 
1565                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1566                                                  gray_color_markup, _("mcen_fi_rootfolder_size"),
1567                                                  size);
1568                 g_free (size);
1569                 
1570                 label_w = gtk_label_new (NULL);
1571                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1572                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1573                 g_free (label);
1574         } else if (TNY_IS_ACCOUNT(folder_store)) {
1575                 TnyAccount *account = TNY_ACCOUNT(folder_store);
1576                 
1577                 time_t last_updated;
1578                 gchar *last_updated_string;
1579                 /* Get last updated from configuration */
1580                 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (), 
1581                                                           tny_account_get_id (account), 
1582                                                           MODEST_ACCOUNT_LAST_UPDATED, 
1583                                                           TRUE);
1584                 if (last_updated > 0) 
1585                         last_updated_string = modest_text_utils_get_display_date(last_updated);
1586                 else
1587                         last_updated_string = g_strdup (_("mcen_va_never"));
1588
1589                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1590                                                  gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1591                 label_w = gtk_label_new (NULL);
1592                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1593                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1594                 g_free (last_updated_string);
1595                 g_free (label);
1596         }
1597
1598         g_free (gray_color_markup);
1599
1600         /* Set alignment */
1601         gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1602
1603         return vbox;
1604 }
1605
1606 gboolean
1607 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1608 {
1609         ModestMainWindowPrivate *priv = NULL;
1610         
1611         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1612
1613         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1614
1615         return priv->send_receive_in_progress;
1616 }
1617
1618 void 
1619 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1620 {
1621         GtkAction *action = NULL;
1622         GtkWidget *widget = NULL;
1623         ModestMainWindowPrivate *priv = NULL;
1624                 
1625         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1626         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1627         
1628         priv->send_receive_in_progress  = TRUE;
1629
1630         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1631         gtk_action_set_sensitive (action, FALSE);
1632 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1633 /*      gtk_action_set_sensitive (action, FALSE); */
1634         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1635         gtk_widget_set_sensitive (widget, FALSE);
1636
1637
1638 void 
1639 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1640 {
1641         GtkAction *action = NULL;
1642         GtkWidget *widget = NULL;
1643         ModestMainWindowPrivate *priv = NULL;
1644                 
1645         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1646         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1647
1648         priv->send_receive_in_progress  = FALSE;
1649
1650         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1651         gtk_action_set_sensitive (action, TRUE);
1652 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu");     */
1653 /*      gtk_action_set_sensitive (action, TRUE); */
1654         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1655         gtk_widget_set_sensitive (widget, TRUE);
1656
1657
1658
1659 static void
1660 _on_msg_count_changed (ModestHeaderView *header_view,
1661                        TnyFolder *folder,
1662                        TnyFolderChange *change,
1663                        ModestMainWindow *main_window)
1664 {
1665         printf ("DEBUG: %s\n", __FUNCTION__);
1666         gboolean folder_empty = FALSE;
1667         TnyFolderChangeChanged changed;
1668         
1669         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1670         g_return_if_fail (TNY_IS_FOLDER(folder));
1671         g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1672         
1673         changed = tny_folder_change_get_changed (change);
1674         
1675         /* If something changes */
1676         if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1677                 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);     
1678         else
1679                 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1680         
1681         printf ("DEBUG: %s: folder_empty=%d\n", __FUNCTION__, folder_empty);
1682
1683         /* Set contents style of headers view */
1684         if (folder_empty)  {
1685                 modest_main_window_set_contents_style (main_window,
1686                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1687         }
1688         else {
1689                 modest_main_window_set_contents_style (main_window,
1690                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1691         }       
1692 }
1693
1694
1695 void 
1696 modest_main_window_set_contents_style (ModestMainWindow *self, 
1697                                        ModestMainWindowContentsStyle style)
1698 {
1699         ModestMainWindowPrivate *priv;
1700
1701         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1702
1703         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1704
1705         /* We allow to set the same content style than the previously
1706            set if there are details, because it could happen when we're
1707            selecting different accounts consecutively */
1708         if ((priv->contents_style == style) &&
1709             (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1710                 return;
1711
1712         /* Remove previous child. Delete it if it was an account
1713            details widget */
1714         GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1715         if (content) {
1716                 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1717                         g_object_ref (content);
1718                 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1719                         g_object_ref (priv->empty_view);
1720                         gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1721                 }
1722                 
1723                 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1724         }
1725
1726         priv->contents_style = style;
1727
1728         switch (priv->contents_style) {
1729         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1730                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1731                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1732                                                       TRUE);
1733                 break;
1734         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1735         {
1736                 TnyFolderStore *selected_folderstore = 
1737                         modest_folder_view_get_selected (priv->folder_view);
1738                 if (TNY_IS_ACCOUNT (selected_folderstore)) {    
1739                   priv->details_widget = create_details_widget (GTK_WIDGET (self),
1740                                                                 TNY_ACCOUNT (selected_folderstore));
1741
1742                         wrap_in_scrolled_window (priv->contents_widget, 
1743                                          priv->details_widget);
1744                 }
1745                 g_object_unref (selected_folderstore);
1746                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1747                                                       FALSE);
1748
1749                 
1750                 break;
1751         }
1752         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1753                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1754                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1755                                                       FALSE);
1756                 break;
1757         default:
1758                 g_return_if_reached ();
1759         }
1760
1761         /* Show */
1762         gtk_widget_show_all (priv->contents_widget);
1763 }
1764
1765 ModestMainWindowContentsStyle
1766 modest_main_window_get_contents_style (ModestMainWindow *self)
1767 {
1768         ModestMainWindowPrivate *priv;
1769
1770         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1771
1772         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1773         return priv->contents_style;
1774 }
1775
1776
1777 static void 
1778 on_configuration_key_changed (ModestConf* conf, 
1779                               const gchar *key, 
1780                               ModestConfEvent event, 
1781                               ModestMainWindow *self)
1782 {
1783         ModestMainWindowPrivate *priv;
1784         TnyAccount *account;
1785
1786         if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1787                 return;
1788
1789         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1790
1791         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1792                 return;
1793
1794         account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1795         if (TNY_IS_ACCOUNT (account) &&
1796             !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1797                 GList *children;
1798                 GtkLabel *label;
1799                 const gchar *device_name;
1800                 gchar *new_text;
1801                 
1802                 /* Get label */
1803                 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1804                 label = GTK_LABEL (children->data);
1805                 
1806                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1807                                                       MODEST_CONF_DEVICE_NAME, NULL);
1808                 
1809                 new_text = g_strdup_printf ("%s: %s",
1810                                             _("mcen_fi_localroot_description"),
1811                                             device_name);
1812                 
1813                 gtk_label_set_text (label, new_text);
1814                 gtk_widget_show (GTK_WIDGET (label));
1815                 
1816                 g_free (new_text);
1817                 g_list_free (children);
1818         }
1819         g_object_unref (account);
1820 }
1821
1822 static gboolean
1823 set_toolbar_transfer_mode (ModestMainWindow *self)
1824 {
1825         ModestMainWindowPrivate *priv = NULL;
1826         
1827         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1828
1829         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1830
1831         set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1832         
1833         if (priv->progress_bar_timeout > 0) {
1834                 g_source_remove (priv->progress_bar_timeout);
1835                 priv->progress_bar_timeout = 0;
1836         }
1837
1838         return FALSE;
1839 }
1840
1841 static void 
1842 set_toolbar_mode (ModestMainWindow *self, 
1843                   ModestToolBarModes mode)
1844 {
1845         ModestWindowPrivate *parent_priv = NULL;
1846         ModestMainWindowPrivate *priv = NULL;
1847         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1848         
1849         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1850
1851         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1852         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1853
1854         /* In case this was called before the toolbar exists: */
1855         if (!(parent_priv->toolbar))
1856                 return;
1857
1858         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
1859         
1860         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1861         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1862         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1863
1864         /* Sets current toolbar mode */
1865         priv->current_toolbar_mode = mode;
1866
1867         /* Show and hide toolbar items */
1868         switch (mode) {
1869         case TOOLBAR_MODE_NORMAL:
1870                 if (sort_action)
1871                         gtk_action_set_visible (sort_action, TRUE);
1872                 if (refresh_action)
1873                         gtk_action_set_visible (refresh_action, TRUE);
1874                 if (priv->progress_toolitem) {
1875                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1876                         gtk_widget_hide (priv->progress_toolitem);
1877                 }
1878                 if (priv->progress_bar)
1879                         gtk_widget_hide (priv->progress_bar);
1880                 
1881                 if (cancel_action)
1882                         gtk_action_set_visible (cancel_action, FALSE);
1883 /*              if (priv->sort_toolitem) */
1884 /*                      gtk_widget_show (priv->sort_toolitem); */
1885                 
1886 /*              if (priv->refresh_toolitem) */
1887 /*                      gtk_widget_show (priv->refresh_toolitem); */
1888                         
1889 /*              if (priv->progress_toolitem) */
1890 /*                      gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE); */
1891 /*              if (priv->progress_bar) */
1892 /*                      gtk_widget_hide (priv->progress_bar); */
1893                         
1894 /*              if (priv->cancel_toolitem) */
1895 /*                      gtk_widget_hide (priv->cancel_toolitem); */
1896
1897                 /* Hide toolbar if optimized view is enabled */
1898                 if (priv->optimized_view)
1899                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1900                 break;
1901         case TOOLBAR_MODE_TRANSFER:
1902                 if (sort_action)
1903                         gtk_action_set_visible (sort_action, FALSE);
1904                 if (refresh_action)
1905                         gtk_action_set_visible (refresh_action, FALSE);
1906                 if (cancel_action)
1907                         gtk_action_set_visible (cancel_action, TRUE);
1908                 if (priv->progress_toolitem) {
1909                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1910                         gtk_widget_show (priv->progress_toolitem);
1911                 }
1912                 if (priv->progress_bar)
1913                         gtk_widget_show (priv->progress_bar);
1914
1915 /*              if (priv->sort_toolitem) */
1916 /*                      gtk_widget_hide (priv->sort_toolitem); */
1917                 
1918 /*              if (priv->refresh_toolitem) */
1919 /*                      gtk_widget_hide (priv->refresh_toolitem); */
1920                 
1921 /*              if (priv->progress_toolitem) */
1922 /*                      gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE); */
1923 /*              if (priv->progress_bar) */
1924 /*                      gtk_widget_show (priv->progress_bar); */
1925                         
1926 /*              if (priv->cancel_toolitem) */
1927 /*                      gtk_widget_show (priv->cancel_toolitem); */
1928
1929                 /* Show toolbar if it's hiden (optimized view ) */
1930                 if (priv->optimized_view)
1931                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1932                 break;
1933         default:
1934                 g_return_if_reached ();
1935         }
1936 }
1937
1938 static void
1939 cancel_progressbar (GtkToolButton *toolbutton,
1940                     ModestMainWindow *self)
1941 {
1942         GSList *tmp;
1943         ModestMainWindowPrivate *priv;
1944         
1945         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1946
1947         /* Get operation observers and cancel its current operation */
1948         tmp = priv->progress_widgets;
1949         while (tmp) {
1950                 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
1951                 tmp=g_slist_next(tmp);
1952         }
1953 }
1954
1955 static gboolean
1956 observers_empty (ModestMainWindow *self)
1957 {
1958         GSList *tmp = NULL;
1959         ModestMainWindowPrivate *priv;
1960         gboolean is_empty = TRUE;
1961         guint pending_ops = 0;
1962  
1963         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1964         tmp = priv->progress_widgets;
1965
1966         /* Check all observers */
1967         while (tmp && is_empty)  {
1968                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1969                 is_empty = pending_ops == 0;
1970                 
1971                 tmp = g_slist_next(tmp);
1972         }
1973         
1974         return is_empty;
1975 }
1976
1977 static void
1978 on_queue_changed (ModestMailOperationQueue *queue,
1979                   ModestMailOperation *mail_op,
1980                   ModestMailOperationQueueNotification type,
1981                   ModestMainWindow *self)
1982 {
1983         ModestMainWindowPrivate *priv;
1984         ModestMailOperationTypeOperation op_type;
1985         ModestToolBarModes mode;
1986         GSList *tmp;
1987         gboolean mode_changed = FALSE;
1988 /*      ModestMailOperationStatus status; */
1989
1990         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1991         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1992                
1993         /* Get toolbar mode from operation id*/
1994         op_type = modest_mail_operation_get_type_operation (mail_op);
1995         switch (op_type) {
1996 /*      case MODEST_MAIL_OPERATION_TYPE_SEND: */
1997         case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1998         case MODEST_MAIL_OPERATION_TYPE_OPEN:
1999                 mode = TOOLBAR_MODE_TRANSFER;
2000                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2001                         mode_changed = TRUE;
2002                 break;
2003         default:
2004                 mode = TOOLBAR_MODE_NORMAL;
2005                 
2006         }
2007                 
2008                        
2009         /* Add operation observers and change toolbar if neccessary*/
2010         tmp = priv->progress_widgets;
2011         switch (type) {
2012         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
2013                 if (mode == TOOLBAR_MODE_TRANSFER) {
2014                         if (mode_changed)
2015                                 set_toolbar_transfer_mode(self);                    
2016                         while (tmp) {
2017                                 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2018                                                                       mail_op);
2019                                 tmp = g_slist_next (tmp);
2020                         }
2021                 }
2022                 break;
2023         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
2024                 /* Change toolbar mode */
2025                 if (mode == TOOLBAR_MODE_TRANSFER) {                    
2026                         while (tmp) {
2027                                 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2028                                                                          mail_op);
2029                                 tmp = g_slist_next (tmp);
2030                         }
2031                         
2032                         /* If no more operations are being observed, NORMAL mode is enabled again */
2033                         if (observers_empty (self)) {
2034                                 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2035                                 
2036                         }
2037                 }
2038
2039                 break;
2040         }       
2041
2042 }
2043
2044 static void 
2045 on_show_account_action_activated  (GtkAction *action,
2046                                    gpointer user_data)
2047 {
2048         ModestAccountData *acc_data;
2049         ModestMainWindow *self;
2050         ModestMainWindowPrivate *priv;
2051         ModestAccountMgr *mgr;
2052         const gchar *acc_name;
2053
2054         self = MODEST_MAIN_WINDOW (user_data);
2055         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2056
2057         /* Get account data */
2058         acc_name = gtk_action_get_name (action);
2059         mgr = modest_runtime_get_account_mgr ();
2060         acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2061
2062         /* Set the new visible & active account */
2063         if (acc_data->store_account) { 
2064                 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2065                                                                              acc_data->store_account->account_name);
2066                 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2067         }
2068
2069         /* Free */
2070         modest_account_mgr_free_account_data (mgr, acc_data);
2071 }
2072
2073 static void
2074 refresh_account (const gchar *account_name)
2075 {
2076         ModestWindow *win;
2077
2078         win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2079
2080         /* If account_name == NULL, we must update all (option All) */
2081         if (!account_name)
2082                 modest_ui_actions_do_send_receive_all (win);
2083         else
2084                 modest_ui_actions_do_send_receive (account_name, win);
2085         
2086 }
2087
2088 static void 
2089 on_refresh_account_action_activated  (GtkAction *action,
2090                                       gpointer user_data)
2091 {
2092         refresh_account ((const gchar*) user_data);
2093 }
2094
2095 static void
2096 on_send_receive_csm_activated (GtkMenuItem *item,
2097                                gpointer user_data)
2098 {
2099         refresh_account ((const gchar*) user_data);
2100 }
2101
2102 static gboolean
2103 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2104 {
2105         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2106
2107         hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2108         return FALSE;
2109
2110 }
2111
2112 static gboolean
2113 on_folder_view_focus_in (GtkWidget *widget,
2114                          GdkEventFocus *event,
2115                          gpointer userdata)
2116 {
2117         ModestMainWindow *main_window = NULL;
2118         
2119         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2120         main_window = MODEST_MAIN_WINDOW (userdata);
2121         
2122         /* Update toolbar dimming state */
2123         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2124
2125         return FALSE;
2126 }
2127
2128 static gboolean
2129 on_header_view_focus_in (GtkWidget *widget,
2130                          GdkEventFocus *event,
2131                          gpointer userdata)
2132 {
2133         ModestMainWindow *main_window = NULL;
2134         ModestMainWindowPrivate *priv = NULL;
2135
2136         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2137         main_window = MODEST_MAIN_WINDOW (userdata);
2138         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2139
2140         if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
2141                 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
2142                 TnyIterator *iterator = tny_list_create_iterator (selection);
2143                 TnyHeader *header;
2144
2145                 tny_iterator_first (iterator);
2146                 header = TNY_HEADER (tny_iterator_get_current (iterator));
2147                 
2148                 if (tny_header_get_subject (header))
2149                         gtk_window_set_title (GTK_WINDOW(main_window), tny_header_get_subject (header));
2150                 else
2151                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
2152
2153                 g_object_unref (header);
2154                 g_object_unref (iterator);
2155                 g_object_unref (selection);
2156         }
2157
2158
2159         /* Update toolbar dimming state */
2160         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2161
2162         return FALSE;
2163 }
2164
2165 static void 
2166 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2167                                                 TnyFolderStore *folder_store, 
2168                                                 gboolean selected,
2169                                                 ModestMainWindow *main_window)
2170 {
2171         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2172         GtkAction *action = NULL;
2173         gboolean show_reply = TRUE;
2174         gboolean show_forward = TRUE;
2175         gboolean show_cancel_send = FALSE;
2176         gboolean show_clipboard = TRUE;
2177         gboolean show_delete = TRUE;
2178
2179         if (selected) {
2180                 if (TNY_IS_ACCOUNT (folder_store)) {
2181                         show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2182                 } else if (TNY_IS_FOLDER (folder_store)) {
2183                         if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2184                                 TnyFolderType folder_type = modest_tny_folder_get_local_folder_type (
2185                                         TNY_FOLDER (folder_store));
2186                                 switch (folder_type) {
2187                                 case TNY_FOLDER_TYPE_DRAFTS:
2188                                         show_clipboard = show_delete = TRUE;
2189                                         show_reply = show_forward = show_cancel_send = FALSE;
2190                                         break;
2191                                 case TNY_FOLDER_TYPE_SENT:
2192                                         show_forward = show_clipboard = show_delete = TRUE;
2193                                         show_reply = show_cancel_send = FALSE;
2194                                         break;
2195                                 case TNY_FOLDER_TYPE_OUTBOX:
2196                                         show_clipboard = show_delete = show_cancel_send = TRUE;
2197                                         show_reply = show_forward = FALSE;
2198                                         break;
2199                                 default:
2200                                         show_reply = show_forward = show_clipboard = show_delete = TRUE;
2201                                         show_cancel_send = FALSE;
2202                                 }
2203                         } else {
2204                                 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2205                                 show_cancel_send = FALSE;
2206                         }
2207                 }
2208         }
2209
2210         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2211         gtk_action_set_visible (action, show_reply);
2212         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2213         gtk_action_set_visible (action, show_reply);
2214         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2215         gtk_action_set_visible (action, show_forward);
2216         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2217         gtk_action_set_visible (action, show_cancel_send);
2218         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCut");
2219         gtk_action_set_visible (action, show_clipboard);
2220         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCopy");
2221         gtk_action_set_visible (action, show_clipboard);
2222         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMPaste");
2223         gtk_action_set_visible (action, show_clipboard);
2224         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2225         gtk_action_set_visible (action, show_delete);
2226
2227         /* We finally call to the ui actions handler, after updating properly
2228          * the header view CSM */
2229         modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2230
2231 }
2232
2233 gboolean 
2234 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2235                                                    GtkTreeModel *model,
2236                                                    GtkTreeRowReference *row_reference,
2237                                                    ModestMainWindow *self)
2238 {
2239         ModestMainWindowPrivate *priv = NULL;
2240         GtkTreeModel *header_model = NULL;
2241         GtkTreePath *path = NULL;
2242
2243         g_return_val_if_fail (MODEST_MSG_VIEW_WINDOW (view_window), FALSE);
2244         g_return_val_if_fail (MODEST_MAIN_WINDOW (self), FALSE);
2245         g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2246
2247         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2248         header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2249
2250         /* Do nothing if we changed the folder in the main view */
2251         if (header_model != model)
2252                 return FALSE;
2253
2254         /* Select the message in the header view */
2255         path = gtk_tree_row_reference_get_path (row_reference);
2256         _modest_header_view_select_from_path (MODEST_HEADER_VIEW (priv->header_view), path);
2257         gtk_tree_path_free (path);
2258
2259         return TRUE;
2260 }