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