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