2007-07-31 Philip Van Hoof <pvanhoof@gnome.org>
[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) > 1);
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_data->account_name) {
1371                         gchar* item_name, *refresh_action_name;
1372                         guint8 merge_id = 0;
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                         printf("DEBUG: %s: menu display_name=%s\n", __FUNCTION__, display_name);
1405                         gtk_action_group_add_action (action_group, refresh_account_action);
1406
1407                         merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1408                         priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1409                         gtk_ui_manager_add_ui (parent_priv->ui_manager, 
1410                                                merge_id,
1411                                                "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
1412                                                item_name,
1413                                                refresh_action_name,
1414                                                GTK_UI_MANAGER_MENUITEM,
1415                                                FALSE);
1416                         g_free (refresh_action_name);
1417
1418                         g_signal_connect_data (G_OBJECT (refresh_account_action), 
1419                                                "activate", 
1420                                                G_CALLBACK (on_refresh_account_action_activated), 
1421                                                g_strdup (account_data->account_name),
1422                                                (GClosureNotify) g_free,
1423                                                0);
1424
1425                         /* Create item and add it to the send&receive
1426                            CSM. If there is only one account then
1427                            it'll be no menu */
1428                         if (priv->accounts_popup) {
1429                                 GtkWidget *label = gtk_label_new(NULL);
1430                                 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1431                                 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
1432                                 {
1433                                         gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
1434                                         gtk_label_set_markup (GTK_LABEL (label), escaped);
1435                                         g_free (escaped);
1436                                 }
1437                                 else
1438                                 {
1439                                         gtk_label_set_text (GTK_LABEL (label), display_name);
1440                                 }
1441
1442                                 item = gtk_menu_item_new ();
1443                                 gtk_container_add (GTK_CONTAINER (item), label);
1444
1445                                 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1446                                 g_signal_connect_data (G_OBJECT (item), 
1447                                                        "activate", 
1448                                                        G_CALLBACK (on_send_receive_csm_activated),
1449                                                        g_strdup (account_data->account_name),
1450                                                        (GClosureNotify) g_free,
1451                                                        0);
1452                         }
1453                         g_free (item_name);
1454                 }
1455
1456                 /* Frees */
1457                 g_free (display_name);
1458         }
1459
1460         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1461
1462         /* We cannot do this in the loop above because this relies on the action
1463          * group being inserted. This makes the default account appear in bold.
1464          * I agree it is a rather ugly way, but I don't see another possibility. armin. */
1465         for (i = 0; i < num_accounts; i++) {
1466                 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1467
1468                 if(account_data->account_name && default_account &&
1469                    strcmp (account_data->account_name, default_account) == 0) {
1470                         gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1471
1472                         gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
1473                         GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1474                         g_free(path);
1475
1476                         if (item) {
1477                                 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1478                                 if (GTK_IS_LABEL (child)) {
1479                                         const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1480                                         gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1481                                         gtk_label_set_markup (GTK_LABEL (child), bold_name);
1482                                         g_free (bold_name);
1483                                 }
1484                         }
1485
1486                         path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
1487                         item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
1488                         g_free (path);
1489
1490                         if (item) {
1491                                 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
1492                                 if (GTK_IS_LABEL (child)) {
1493                                         const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
1494                                         gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
1495                                         gtk_label_set_markup (GTK_LABEL (child), bold_name);
1496                                         g_free (bold_name);
1497                                 }
1498                         }
1499
1500                         g_free(item_name);
1501                 }
1502
1503                 modest_account_mgr_free_account_data (mgr, account_data);
1504         }
1505
1506         if (priv->accounts_popup) {
1507                 /* Mandatory in order to view the menu contents */
1508                 gtk_widget_show_all (priv->accounts_popup);
1509
1510                 /* Setup tap_and_hold just if was not done before*/
1511                 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1512                         gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1513         }
1514
1515         /* Frees */
1516         g_slist_free (accounts);
1517         g_free (default_account);
1518 }
1519
1520 /* 
1521  * This function manages the key events used to navigate between
1522  * header and folder views (when the window is in split view)
1523  *
1524  * FROM         KEY        ACTION
1525  * -------------------------------------------------
1526  * HeaderView   GDK_Left   Move focus to folder view
1527  * FolderView   GDK_Right  Move focus to header view
1528  *
1529  * There is no need to scroll to selected row, the widgets will be the
1530  * responsibles of doing that (probably managing the focus-in event
1531  */
1532 static gboolean 
1533 on_inner_widgets_key_pressed (GtkWidget *widget,
1534                               GdkEventKey *event,
1535                               gpointer user_data)
1536 {
1537         ModestMainWindowPrivate *priv;
1538
1539         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1540
1541         /* Do nothing if we're in SIMPLE style */
1542         if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1543                 return FALSE;
1544
1545         if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1546                 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1547         else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1548                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1549
1550         return FALSE;
1551 }
1552
1553 static void
1554 set_alignment (GtkWidget *widget,
1555                gpointer data)
1556 {
1557         gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1558         gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1559 }
1560
1561 static GtkWidget *
1562 create_empty_view (void)
1563 {
1564         GtkLabel *label = NULL;
1565         GtkWidget *align = NULL;
1566
1567         align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1568         label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1569         gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);      
1570         gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1571
1572         return GTK_WIDGET(align);
1573 }
1574
1575 static GtkWidget *
1576 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1577 {
1578         /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1579         
1580         GtkWidget *vbox;
1581         GtkWidget *label_w;
1582         gchar *label;
1583         gchar *gray_color_markup;
1584
1585         vbox = gtk_vbox_new (FALSE, 0);
1586
1587         /* Obtain the secondary text color. We need a realized widget, that's why 
1588            we get styled_widget from outside */
1589 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1590         GdkColor color;
1591         gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1592         gray_color_markup = modest_text_utils_get_color_string (&color);
1593 #else
1594         // gray_color_markup is freed below
1595         gray_color_markup = g_strdup ("#BBBBBB");
1596 #endif  
1597         /* Account description: */
1598         
1599         if (modest_tny_account_is_virtual_local_folders (account)
1600                 || (modest_tny_account_is_memory_card_account (account))) {
1601                 gchar *tmp;
1602                 /* Local folders: */
1603         
1604                 /* Get device name */
1605                 gchar *device_name = NULL;
1606                 if (modest_tny_account_is_virtual_local_folders (account))
1607                         device_name = modest_conf_get_string (modest_runtime_get_conf(),
1608                                                       MODEST_CONF_DEVICE_NAME, NULL);
1609                 else
1610                         device_name = g_strdup (tny_account_get_name (account));
1611                                                       
1612                 tmp = g_strdup_printf (_("mcen_fi_localroot_description"), ""); //TODO: Why the ""?
1613                 label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s",
1614                                                  gray_color_markup, tmp, device_name);
1615                 g_free (tmp);
1616                 label_w = gtk_label_new (NULL);
1617                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1618                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1619                 g_free (device_name);
1620                 g_free (label);
1621         } else {
1622                 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1623                         gtk_box_pack_start (GTK_BOX (vbox), 
1624                                 gtk_label_new (tny_account_get_name (account)), 
1625                                 FALSE, FALSE, 0);
1626                 } else {
1627                         /* Other accounts, such as IMAP and POP: */
1628                         
1629                         GString *proto;
1630                         gchar *tmp;
1631         
1632                         /* Put proto in uppercase */
1633                         proto = g_string_new (tny_account_get_proto (account));
1634                         proto = g_string_ascii_up (proto);
1635                         
1636                         /* note: mcen_fi_localroot_description is something like "%s account"
1637                          * however, we should display "%s account: %s"... therefore, ugly tmp */
1638                         tmp   = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1639                         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1640                                                          gray_color_markup, tmp, tny_account_get_name (account));
1641                         g_free (tmp);
1642
1643                         label_w = gtk_label_new (NULL);
1644                         gtk_label_set_markup (GTK_LABEL (label_w), label);
1645                         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1646                         g_string_free (proto, TRUE);
1647                         g_free (label);
1648                 }
1649         }
1650
1651         /* Message count */
1652         TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1653         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", 
1654                                          gray_color_markup, _("mcen_fi_rootfolder_messages"), 
1655                                          modest_tny_folder_store_get_message_count (folder_store));
1656         label_w = gtk_label_new (NULL);
1657         gtk_label_set_markup (GTK_LABEL (label_w), label);
1658         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1659         g_free (label);
1660
1661         /* Folder count */
1662         label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d", 
1663                                          gray_color_markup, 
1664                                          _("mcen_fi_rootfolder_folders"), 
1665                                          modest_tny_folder_store_get_folder_count (folder_store));
1666         label_w = gtk_label_new (NULL);
1667         gtk_label_set_markup (GTK_LABEL (label_w), label);
1668         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1669         g_free (label);
1670
1671         /* Size / Date */
1672         if (modest_tny_account_is_virtual_local_folders (account)
1673                 || modest_tny_account_is_memory_card_account (account)) {
1674
1675                 gchar *size = modest_text_utils_get_display_size (
1676                         modest_tny_folder_store_get_local_size (folder_store));
1677                 
1678                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1679                                                  gray_color_markup, _("mcen_fi_rootfolder_size"),
1680                                                  size);
1681                 g_free (size);
1682                 
1683                 label_w = gtk_label_new (NULL);
1684                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1685                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1686                 g_free (label);
1687         } else if (TNY_IS_ACCOUNT(folder_store)) {
1688                 TnyAccount *account = TNY_ACCOUNT(folder_store);
1689                 
1690                 time_t last_updated;
1691                 gchar *last_updated_string;
1692                 /* Get last updated from configuration */
1693                 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (), 
1694                                                           tny_account_get_id (account), 
1695                                                           MODEST_ACCOUNT_LAST_UPDATED, 
1696                                                           TRUE);
1697                 if (last_updated > 0) 
1698                         last_updated_string = modest_text_utils_get_display_date(last_updated);
1699                 else
1700                         last_updated_string = g_strdup (_("mcen_va_never"));
1701
1702                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1703                                                  gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1704                 label_w = gtk_label_new (NULL);
1705                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1706                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1707                 g_free (last_updated_string);
1708                 g_free (label);
1709         }
1710
1711         g_free (gray_color_markup);
1712
1713         /* Set alignment */
1714         gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1715
1716         return vbox;
1717 }
1718
1719 gboolean
1720 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1721 {
1722         ModestMainWindowPrivate *priv = NULL;
1723         
1724         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1725
1726         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1727
1728         return priv->send_receive_in_progress;
1729 }
1730
1731 void 
1732 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1733 {
1734         GtkAction *action = NULL;
1735         GtkWidget *widget = NULL;
1736         ModestMainWindowPrivate *priv = NULL;
1737                 
1738         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1739         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1740         
1741         priv->send_receive_in_progress  = TRUE;
1742
1743         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1744         gtk_action_set_sensitive (action, FALSE);
1745 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1746 /*      gtk_action_set_sensitive (action, FALSE); */
1747         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1748         gtk_widget_set_sensitive (widget, FALSE);
1749
1750
1751 void 
1752 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1753 {
1754         GtkAction *action = NULL;
1755         GtkWidget *widget = NULL;
1756         ModestMainWindowPrivate *priv = NULL;
1757                 
1758         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1759         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1760
1761         priv->send_receive_in_progress  = FALSE;
1762
1763         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1764         gtk_action_set_sensitive (action, TRUE);
1765 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu");     */
1766 /*      gtk_action_set_sensitive (action, TRUE); */
1767         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1768         gtk_widget_set_sensitive (widget, TRUE);
1769
1770
1771
1772 static void
1773 _on_msg_count_changed (ModestHeaderView *header_view,
1774                        TnyFolder *folder,
1775                        TnyFolderChange *change,
1776                        ModestMainWindow *main_window)
1777 {
1778         printf ("DEBUG: %s\n", __FUNCTION__);
1779         gboolean folder_empty = FALSE;
1780         TnyFolderChangeChanged changed; 
1781         ModestMainWindowPrivate *priv;
1782         
1783         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1784         g_return_if_fail (TNY_IS_FOLDER(folder));
1785         g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1786         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1787         
1788         changed = tny_folder_change_get_changed (change);
1789         
1790         /* If something changes */
1791         if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1792                 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);     
1793         else
1794                 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1795         
1796         printf ("DEBUG: %s: folder_empty=%d\n", __FUNCTION__, folder_empty);
1797
1798         /* Set contents style of headers view */
1799         if (folder_empty)  {
1800                 modest_main_window_set_contents_style (main_window,
1801                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1802                 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1803         }
1804         else {
1805                 modest_main_window_set_contents_style (main_window,
1806                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1807         }       
1808 }
1809
1810
1811 void 
1812 modest_main_window_set_contents_style (ModestMainWindow *self, 
1813                                        ModestMainWindowContentsStyle style)
1814 {
1815         ModestMainWindowPrivate *priv;
1816
1817         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1818
1819         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1820
1821         /* We allow to set the same content style than the previously
1822            set if there are details, because it could happen when we're
1823            selecting different accounts consecutively */
1824         if ((priv->contents_style == style) &&
1825             (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1826                 return;
1827
1828         /* Remove previous child. Delete it if it was an account
1829            details widget */
1830         GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1831         if (content) {
1832                 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1833                         g_object_ref (content);
1834                 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1835                         g_object_ref (priv->empty_view);
1836                         gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1837                 }
1838                 
1839                 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1840         }
1841
1842         priv->contents_style = style;
1843
1844         switch (priv->contents_style) {
1845         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1846                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1847                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1848                                                       TRUE);
1849                 break;
1850         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1851         {
1852                 TnyFolderStore *selected_folderstore = 
1853                         modest_folder_view_get_selected (priv->folder_view);
1854                 if (TNY_IS_ACCOUNT (selected_folderstore)) {    
1855                   priv->details_widget = create_details_widget (GTK_WIDGET (self),
1856                                                                 TNY_ACCOUNT (selected_folderstore));
1857
1858                         wrap_in_scrolled_window (priv->contents_widget, 
1859                                          priv->details_widget);
1860                 }
1861                 g_object_unref (selected_folderstore);
1862                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1863                                                       FALSE);
1864
1865                 
1866                 break;
1867         }
1868         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1869                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1870                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1871                                                       FALSE);
1872                 break;
1873         default:
1874                 g_return_if_reached ();
1875         }
1876
1877         /* Show */
1878         gtk_widget_show_all (priv->contents_widget);
1879 }
1880
1881 ModestMainWindowContentsStyle
1882 modest_main_window_get_contents_style (ModestMainWindow *self)
1883 {
1884         ModestMainWindowPrivate *priv;
1885
1886         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1887
1888         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1889         return priv->contents_style;
1890 }
1891
1892
1893 static void 
1894 on_configuration_key_changed (ModestConf* conf, 
1895                               const gchar *key, 
1896                               ModestConfEvent event,
1897                               ModestConfNotificationId id, 
1898                               ModestMainWindow *self)
1899 {
1900         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1901         TnyAccount *account;
1902
1903         if (!key || 
1904             priv->notification_id != id ||
1905             strcmp (key, MODEST_CONF_DEVICE_NAME))
1906                 return;
1907
1908         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1909                 return;
1910
1911         account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1912         if (TNY_IS_ACCOUNT (account) &&
1913             !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1914                 GList *children;
1915                 GtkLabel *label;
1916                 const gchar *device_name;
1917                 gchar *new_text;
1918                 
1919                 /* Get label */
1920                 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1921                 label = GTK_LABEL (children->data);
1922                 
1923                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1924                                                       MODEST_CONF_DEVICE_NAME, NULL);
1925                 
1926                 new_text = g_strdup_printf ("%s: %s",
1927                                             _("mcen_fi_localroot_description"),
1928                                             device_name);
1929                 
1930                 gtk_label_set_text (label, new_text);
1931                 gtk_widget_show (GTK_WIDGET (label));
1932                 
1933                 g_free (new_text);
1934                 g_list_free (children);
1935         }
1936         g_object_unref (account);
1937 }
1938
1939 static gboolean
1940 set_toolbar_transfer_mode (ModestMainWindow *self)
1941 {
1942         ModestMainWindowPrivate *priv = NULL;
1943         
1944         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1945
1946         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1947
1948         set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1949         
1950         if (priv->progress_bar_timeout > 0) {
1951                 g_source_remove (priv->progress_bar_timeout);
1952                 priv->progress_bar_timeout = 0;
1953         }
1954
1955         return FALSE;
1956 }
1957
1958 static void 
1959 set_toolbar_mode (ModestMainWindow *self, 
1960                   ModestToolBarModes mode)
1961 {
1962         ModestWindowPrivate *parent_priv = NULL;
1963         ModestMainWindowPrivate *priv = NULL;
1964         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1965         
1966         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1967
1968         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1969         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1970
1971         /* In case this was called before the toolbar exists: */
1972         if (!(parent_priv->toolbar))
1973                 return;
1974
1975         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
1976         
1977         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1978         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1979         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1980
1981         /* Sets current toolbar mode */
1982         priv->current_toolbar_mode = mode;
1983
1984         /* Show and hide toolbar items */
1985         switch (mode) {
1986         case TOOLBAR_MODE_NORMAL:
1987                 if (sort_action)
1988                         gtk_action_set_visible (sort_action, TRUE);
1989                 if (refresh_action)
1990                         gtk_action_set_visible (refresh_action, TRUE);
1991                 if (priv->progress_toolitem) {
1992                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1993                         gtk_widget_hide (priv->progress_toolitem);
1994                 }
1995                 if (priv->progress_bar)
1996                         gtk_widget_hide (priv->progress_bar);
1997                 
1998                 if (cancel_action)
1999                         gtk_action_set_visible (cancel_action, FALSE);
2000 /*              if (priv->sort_toolitem) */
2001 /*                      gtk_widget_show (priv->sort_toolitem); */
2002                 
2003 /*              if (priv->refresh_toolitem) */
2004 /*                      gtk_widget_show (priv->refresh_toolitem); */
2005                         
2006 /*              if (priv->progress_toolitem) */
2007 /*                      gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE); */
2008 /*              if (priv->progress_bar) */
2009 /*                      gtk_widget_hide (priv->progress_bar); */
2010                         
2011 /*              if (priv->cancel_toolitem) */
2012 /*                      gtk_widget_hide (priv->cancel_toolitem); */
2013
2014                 /* Hide toolbar if optimized view is enabled */
2015                 if (priv->optimized_view)
2016                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2017                 break;
2018         case TOOLBAR_MODE_TRANSFER:
2019                 if (sort_action)
2020                         gtk_action_set_visible (sort_action, FALSE);
2021                 if (refresh_action)
2022                         gtk_action_set_visible (refresh_action, FALSE);
2023                 if (cancel_action)
2024                         gtk_action_set_visible (cancel_action, TRUE);
2025                 if (priv->progress_toolitem) {
2026                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2027                         gtk_widget_show (priv->progress_toolitem);
2028                 }
2029                 if (priv->progress_bar)
2030                         gtk_widget_show (priv->progress_bar);
2031
2032 /*              if (priv->sort_toolitem) */
2033 /*                      gtk_widget_hide (priv->sort_toolitem); */
2034                 
2035 /*              if (priv->refresh_toolitem) */
2036 /*                      gtk_widget_hide (priv->refresh_toolitem); */
2037                 
2038 /*              if (priv->progress_toolitem) */
2039 /*                      gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE); */
2040 /*              if (priv->progress_bar) */
2041 /*                      gtk_widget_show (priv->progress_bar); */
2042                         
2043 /*              if (priv->cancel_toolitem) */
2044 /*                      gtk_widget_show (priv->cancel_toolitem); */
2045
2046                 /* Show toolbar if it's hiden (optimized view ) */
2047                 if (priv->optimized_view)
2048                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2049                 break;
2050         default:
2051                 g_return_if_reached ();
2052         }
2053 }
2054
2055 static void
2056 cancel_progressbar (GtkToolButton *toolbutton,
2057                     ModestMainWindow *self)
2058 {
2059         GSList *tmp;
2060         ModestMainWindowPrivate *priv;
2061         
2062         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2063
2064         /* Get operation observers and cancel all the operations */
2065         tmp = priv->progress_widgets;
2066         while (tmp) {
2067                 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2068                 tmp=g_slist_next(tmp);
2069         }
2070 }
2071
2072 static gboolean
2073 observers_empty (ModestMainWindow *self)
2074 {
2075         GSList *tmp = NULL;
2076         ModestMainWindowPrivate *priv;
2077         gboolean is_empty = TRUE;
2078         guint pending_ops = 0;
2079  
2080         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2081         tmp = priv->progress_widgets;
2082
2083         /* Check all observers */
2084         while (tmp && is_empty)  {
2085                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2086                 is_empty = pending_ops == 0;
2087                 
2088                 tmp = g_slist_next(tmp);
2089         }
2090         
2091         return is_empty;
2092 }
2093
2094 static void
2095 on_queue_changed (ModestMailOperationQueue *queue,
2096                   ModestMailOperation *mail_op,
2097                   ModestMailOperationQueueNotification type,
2098                   ModestMainWindow *self)
2099 {
2100         ModestMainWindowPrivate *priv;
2101         ModestMailOperationTypeOperation op_type;
2102         ModestToolBarModes mode;
2103         GSList *tmp;
2104         gboolean mode_changed = FALSE;
2105 /*      ModestMailOperationStatus status; */
2106
2107         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2108         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2109                
2110         /* Get toolbar mode from operation id*/
2111         op_type = modest_mail_operation_get_type_operation (mail_op);
2112         switch (op_type) {
2113 /*      case MODEST_MAIL_OPERATION_TYPE_SEND: */
2114         case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2115         case MODEST_MAIL_OPERATION_TYPE_OPEN:
2116                 mode = TOOLBAR_MODE_TRANSFER;
2117                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2118                         mode_changed = TRUE;
2119                 break;
2120         default:
2121                 mode = TOOLBAR_MODE_NORMAL;
2122                 
2123         }
2124                 
2125                        
2126         /* Add operation observers and change toolbar if neccessary*/
2127         tmp = priv->progress_widgets;
2128         switch (type) {
2129         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
2130                 if (mode == TOOLBAR_MODE_TRANSFER) {
2131                         if (mode_changed)
2132                                 set_toolbar_transfer_mode(self);                    
2133                         while (tmp) {
2134                                 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2135                                                                       mail_op);
2136                                 tmp = g_slist_next (tmp);
2137                         }
2138                 }
2139                 break;
2140         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
2141                 /* Change toolbar mode */
2142                 if (mode == TOOLBAR_MODE_TRANSFER) {                    
2143                         while (tmp) {
2144                                 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2145                                                                          mail_op);
2146                                 tmp = g_slist_next (tmp);
2147                         }
2148                         
2149                         /* If no more operations are being observed, NORMAL mode is enabled again */
2150                         if (observers_empty (self)) {
2151                                 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
2152                                 
2153                         }
2154                 }
2155
2156                 break;
2157         }       
2158
2159 }
2160
2161 static void 
2162 on_show_account_action_activated  (GtkAction *action,
2163                                    gpointer user_data)
2164 {
2165         ModestAccountData *acc_data;
2166         ModestMainWindow *self;
2167         ModestMainWindowPrivate *priv;
2168         ModestAccountMgr *mgr;
2169         const gchar *acc_name;
2170
2171         self = MODEST_MAIN_WINDOW (user_data);
2172         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2173
2174         /* Get account data */
2175         acc_name = gtk_action_get_name (action);
2176         mgr = modest_runtime_get_account_mgr ();
2177         acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2178
2179         /* Set the new visible & active account */
2180         if (acc_data && acc_data->store_account) { 
2181                 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2182                                                                              acc_data->store_account->account_name);
2183                 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2184         }
2185         
2186         modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2187
2188         /* Free */
2189         if (acc_data)
2190                 modest_account_mgr_free_account_data (mgr, acc_data);
2191 }
2192
2193 static void
2194 refresh_account (const gchar *account_name)
2195 {
2196         ModestWindow *win;
2197
2198         win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2199
2200         /* If account_name == NULL, we must update all (option All) */
2201         if (!account_name)
2202                 modest_ui_actions_do_send_receive_all (win);
2203         else
2204                 modest_ui_actions_do_send_receive (account_name, win);
2205         
2206 }
2207
2208 static void 
2209 on_refresh_account_action_activated  (GtkAction *action,
2210                                       gpointer user_data)
2211 {
2212         refresh_account ((const gchar*) user_data);
2213 }
2214
2215 static void
2216 on_send_receive_csm_activated (GtkMenuItem *item,
2217                                gpointer user_data)
2218 {
2219         refresh_account ((const gchar*) user_data);
2220 }
2221
2222 static gboolean
2223 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2224 {
2225         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2226
2227         hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2228         return FALSE;
2229
2230 }
2231
2232 static gboolean
2233 on_folder_view_focus_in (GtkWidget *widget,
2234                          GdkEventFocus *event,
2235                          gpointer userdata)
2236 {
2237         ModestMainWindow *main_window = NULL;
2238         
2239         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2240         main_window = MODEST_MAIN_WINDOW (userdata);
2241         
2242         /* Update toolbar dimming state */
2243         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2244
2245         return FALSE;
2246 }
2247
2248 static gboolean
2249 on_header_view_focus_in (GtkWidget *widget,
2250                          GdkEventFocus *event,
2251                          gpointer userdata)
2252 {
2253         ModestMainWindow *main_window = NULL;
2254         ModestMainWindowPrivate *priv = NULL;
2255
2256         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2257         main_window = MODEST_MAIN_WINDOW (userdata);
2258         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2259
2260         if (modest_header_view_has_selected_headers (MODEST_HEADER_VIEW (priv->header_view))) {
2261                 TnyList *selection = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (priv->header_view));
2262                 TnyIterator *iterator = tny_list_create_iterator (selection);
2263                 TnyHeader *header;
2264
2265                 tny_iterator_first (iterator);
2266                 header = TNY_HEADER (tny_iterator_get_current (iterator));
2267                 
2268                 if (tny_header_get_subject (header))
2269                         gtk_window_set_title (GTK_WINDOW(main_window), tny_header_get_subject (header));
2270                 else
2271                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
2272
2273                 if (header)
2274                         g_object_unref (header);
2275
2276                 g_object_unref (iterator);
2277                 g_object_unref (selection);
2278         }
2279
2280
2281         /* Update toolbar dimming state */
2282         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2283
2284         return FALSE;
2285 }
2286
2287 static void 
2288 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2289                                                 TnyFolderStore *folder_store, 
2290                                                 gboolean selected,
2291                                                 ModestMainWindow *main_window)
2292 {
2293         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2294         GtkAction *action = NULL;
2295         gboolean show_reply = TRUE;
2296         gboolean show_forward = TRUE;
2297         gboolean show_cancel_send = FALSE;
2298         gboolean show_clipboard = TRUE;
2299         gboolean show_delete = TRUE;
2300
2301         if (selected) {
2302                 if (TNY_IS_ACCOUNT (folder_store)) {
2303                         show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2304                 } else if (TNY_IS_FOLDER (folder_store)) {
2305                         if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2306                                 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2307                                         TNY_FOLDER (folder_store));
2308                                 switch (folder_type) {
2309                                 case TNY_FOLDER_TYPE_DRAFTS:
2310                                         show_clipboard = show_delete = TRUE;
2311                                         show_reply = show_forward = show_cancel_send = FALSE;
2312                                         break;
2313                                 case TNY_FOLDER_TYPE_SENT:
2314                                         show_forward = show_clipboard = show_delete = TRUE;
2315                                         show_reply = show_cancel_send = FALSE;
2316                                         break;
2317                                 case TNY_FOLDER_TYPE_OUTBOX:
2318                                         show_clipboard = show_delete = show_cancel_send = TRUE;
2319                                         show_reply = show_forward = FALSE;
2320                                         break;
2321                                 default:
2322                                         show_reply = show_forward = show_clipboard = show_delete = TRUE;
2323                                         show_cancel_send = FALSE;
2324                                 }
2325                         } else {
2326                                 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2327                                 show_cancel_send = FALSE;
2328                         }
2329                 }
2330         }
2331
2332         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2333         gtk_action_set_visible (action, show_reply);
2334         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2335         gtk_action_set_visible (action, show_reply);
2336         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2337         gtk_action_set_visible (action, show_forward);
2338         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2339         gtk_action_set_visible (action, show_cancel_send);
2340         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCut");
2341         gtk_action_set_visible (action, show_clipboard);
2342         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCopy");
2343         gtk_action_set_visible (action, show_clipboard);
2344         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMPaste");
2345         gtk_action_set_visible (action, show_clipboard);
2346         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2347         gtk_action_set_visible (action, show_delete);
2348
2349         /* We finally call to the ui actions handler, after updating properly
2350          * the header view CSM */
2351         modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2352
2353 }
2354
2355 gboolean 
2356 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2357                                                    GtkTreeModel *model,
2358                                                    GtkTreeRowReference *row_reference,
2359                                                    ModestMainWindow *self)
2360 {
2361         ModestMainWindowPrivate *priv = NULL;
2362         GtkTreeModel *header_model = NULL;
2363         GtkTreePath *path = NULL;
2364
2365         g_return_val_if_fail (MODEST_MSG_VIEW_WINDOW (view_window), FALSE);
2366         g_return_val_if_fail (MODEST_MAIN_WINDOW (self), FALSE);
2367         g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2368
2369         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2370         header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2371
2372         /* Do nothing if we changed the folder in the main view */
2373         if (header_model != model)
2374                 return FALSE;
2375
2376         /* Select the message in the header view */
2377         path = gtk_tree_row_reference_get_path (row_reference);
2378         gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2379                                   path, NULL, FALSE);
2380         gtk_tree_path_free (path);
2381
2382         return TRUE;
2383 }