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