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