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