e38aa0c74037ade673ab90fee1dc601613090d7b
[modest] / src / modest-ui-actions.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 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <glib/gprintf.h>
36 #include <string.h>
37 #include <modest-runtime.h>
38 #include <modest-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
44 #include "modest-protocol-info.h"
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include "modest-debug.h"
48 #include <tny-mime-part.h>
49 #include <tny-camel-folder.h>
50 #include <tny-camel-imap-folder.h>
51 #include <tny-camel-pop-folder.h>
52
53 #ifdef MODEST_PLATFORM_MAEMO
54 #include "maemo/modest-osso-state-saving.h"
55 #include "maemo/modest-hildon-includes.h"
56 #include "maemo/modest-connection-specific-smtp-window.h"
57 #endif /* MODEST_PLATFORM_MAEMO */
58 #include <modest-utils.h>
59
60 #include "widgets/modest-ui-constants.h"
61 #include <widgets/modest-main-window.h>
62 #include <widgets/modest-msg-view-window.h>
63 #include <widgets/modest-account-view-window.h>
64 #include <widgets/modest-details-dialog.h>
65 #include <widgets/modest-attachments-view.h>
66 #include "widgets/modest-folder-view.h"
67 #include "widgets/modest-global-settings-dialog.h"
68 #include "modest-account-mgr-helpers.h"
69 #include "modest-mail-operation.h"
70 #include "modest-text-utils.h"
71
72 #ifdef MODEST_HAVE_EASYSETUP
73 #include "easysetup/modest-easysetup-wizard.h"
74 #endif /* MODEST_HAVE_EASYSETUP */
75
76 #include <modest-widget-memory.h>
77 #include <tny-error.h>
78 #include <tny-simple-list.h>
79 #include <tny-msg-view.h>
80 #include <tny-device.h>
81 #include <tny-merge-folder.h>
82
83 #include <gtkhtml/gtkhtml.h>
84
85 typedef struct _GetMsgAsyncHelper {     
86         ModestWindow *window;
87         ModestMailOperation *mail_op;
88         TnyIterator *iter;
89         guint num_ops;
90         GFunc func;     
91         gpointer user_data;
92 } GetMsgAsyncHelper;
93
94 typedef enum _ReplyForwardAction {
95         ACTION_REPLY,
96         ACTION_REPLY_TO_ALL,
97         ACTION_FORWARD
98 } ReplyForwardAction;
99
100 typedef struct _ReplyForwardHelper {
101         guint reply_forward_type;
102         ReplyForwardAction action;
103         gchar *account_name;
104         GtkWidget *parent_window;
105 } ReplyForwardHelper;
106
107 typedef struct _MoveToHelper {
108         GtkTreeRowReference *reference;
109         GtkWidget *banner;
110 } MoveToHelper;
111
112 typedef struct _PasteAsAttachmentHelper {
113         ModestMsgEditWindow *window;
114         GtkWidget *banner;
115 } PasteAsAttachmentHelper;
116
117
118 /*
119  * The do_headers_action uses this kind of functions to perform some
120  * action to each member of a list of headers
121  */
122 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
123
124 static void     do_headers_action     (ModestWindow *win, 
125                                        HeadersFunc func,
126                                        gpointer user_data);
127
128 static void     open_msg_cb            (ModestMailOperation *mail_op, 
129                                         TnyHeader *header, 
130                                         gboolean canceled,
131                                         TnyMsg *msg,
132                                         GError *err,
133                                         gpointer user_data);
134
135 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
136                                         TnyHeader *header, 
137                                         gboolean canceled,
138                                         TnyMsg *msg,
139                                         GError *err,
140                                         gpointer user_data);
141
142 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
143
144 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
145                                         TnyFolder *folder, 
146                                         gpointer user_data);
147
148 static void     on_send_receive_finished (ModestMailOperation  *mail_op, 
149                                           gpointer user_data);
150
151 static gint header_list_count_uncached_msgs (TnyList *header_list);
152
153 static gboolean connect_to_get_msg (ModestWindow *win,
154                                     gint num_of_uncached_msgs,
155                                     TnyAccount *account);
156
157 static gboolean remote_folder_is_pop (const TnyFolderStore *folder);
158
159 static gboolean msgs_already_deleted_from_server ( TnyList *headers,
160                                                    const TnyFolderStore *src_folder);
161
162 static void     do_create_folder (GtkWindow *window, 
163                                   TnyFolderStore *parent_folder, 
164                                   const gchar *suggested_name);
165
166 /*
167  * This function checks whether a TnyFolderStore is a pop account
168  */
169 static gboolean
170 remote_folder_is_pop (const TnyFolderStore *folder)
171 {
172         const gchar *proto = NULL;
173         TnyAccount *account = NULL;
174
175         g_return_val_if_fail (TNY_IS_FOLDER_STORE(folder), FALSE);
176
177         if (TNY_IS_ACCOUNT (folder)) {
178                 account = TNY_ACCOUNT(folder);
179                 g_object_ref(account);
180         } else if (TNY_IS_FOLDER (folder)) {
181                 account = tny_folder_get_account(TNY_FOLDER(folder));
182         }
183
184         if (!account && !TNY_IS_ACCOUNT(account)) {
185                 g_warning ("%s: could not get account", __FUNCTION__);
186                 return FALSE;
187         }
188         
189         proto = tny_account_get_proto(account);
190         g_object_unref (account);
191
192         return proto &&
193           (modest_protocol_info_get_transport_store_protocol (proto) == MODEST_PROTOCOL_STORE_POP);
194 }
195
196 /*
197  * This functions checks whether if a list of messages are already
198  * deleted from the server: that is, if the server is a POP account
199  * and all messages are already cached.
200  */
201 static gboolean
202 msgs_already_deleted_from_server (TnyList *headers, const TnyFolderStore *src_folder)
203 {
204         g_return_val_if_fail (TNY_IS_FOLDER_STORE(src_folder), FALSE);
205         g_return_val_if_fail (TNY_IS_LIST(headers), FALSE);
206
207         gboolean src_is_pop = remote_folder_is_pop (src_folder);
208         gint uncached_msgs = header_list_count_uncached_msgs (headers);
209
210         return (src_is_pop && !uncached_msgs);
211 }
212
213
214 /* FIXME: this should be merged with the similar code in modest-account-view-window */
215 /* Show the account creation wizard dialog.
216  * returns: TRUE if an account was created. FALSE if the user cancelled.
217  */
218 gboolean
219 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
220 {
221         gboolean result = FALSE;        
222         GtkWindow *dialog, *wizard;
223         gint dialog_response;
224
225         /* Show the easy-setup wizard: */       
226         dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr());
227         if (dialog) {
228                 /* old wizard is active already; 
229                  */
230                 gtk_window_present (GTK_WINDOW(dialog));
231                 return FALSE;
232         }
233         
234
235         /* there is no such wizard yet */       
236         wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
237         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), wizard);
238
239         /* always present a main window in the background 
240          * we do it here, so we cannot end up with two wizards (as this
241          * function might be called in modest_window_mgr_get_main_window as well */
242         if (!win) 
243                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
244                                                          TRUE);  /* create if not existent */
245         
246         /* make sure the mainwindow is visible */
247         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
248         gtk_widget_show_all (GTK_WIDGET(win));
249         gtk_window_present (GTK_WINDOW(win));
250         
251         dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
252         gtk_widget_destroy (GTK_WIDGET (wizard));
253         if (gtk_events_pending ())
254                 gtk_main_iteration ();
255
256         if (dialog_response == GTK_RESPONSE_CANCEL) {
257                 result = FALSE;
258         } else {
259                 /* Check whether an account was created: */
260                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
261         }
262         return result;
263 }
264
265
266 void   
267 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
268 {
269         GtkWidget *about;
270         const gchar *authors[] = {
271                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
272                 NULL
273         };
274         about = gtk_about_dialog_new ();
275         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
276         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
277         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
278                                         _("Copyright (c) 2006, Nokia Corporation\n"
279                                           "All rights reserved."));
280         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
281                                        _("a modest e-mail client\n\n"
282                                          "design and implementation: Dirk-Jan C. Binnema\n"
283                                          "contributions from the fine people at KC and Ig\n"
284                                          "uses the tinymail email framework written by Philip van Hoof"));
285         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
286         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
287         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
288         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
289         
290         gtk_dialog_run (GTK_DIALOG (about));
291         gtk_widget_destroy(about);
292 }
293
294 /*
295  * Gets the list of currently selected messages. If the win is the
296  * main window, then it returns a newly allocated list of the headers
297  * selected in the header view. If win is the msg view window, then
298  * the value returned is a list with just a single header.
299  *
300  * The caller of this funcion must free the list.
301  */
302 static TnyList *
303 get_selected_headers (ModestWindow *win)
304 {
305         if (MODEST_IS_MAIN_WINDOW(win)) {
306                 GtkWidget *header_view;         
307                 
308                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
309                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
310                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
311                 
312         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
313                 /* for MsgViewWindows, we simply return a list with one element */
314                 TnyHeader *header;
315                 TnyList *list = NULL;
316                 
317                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
318                 if (header != NULL) {
319                         list = tny_simple_list_new ();
320                         tny_list_prepend (list, G_OBJECT(header));
321                         g_object_unref (G_OBJECT(header));
322                 }
323
324                 return list;
325
326         } else
327                 return NULL;
328 }
329
330 static GtkTreeRowReference *
331 get_next_after_selected_headers (ModestHeaderView *header_view)
332 {
333         GtkTreeSelection *sel;
334         GList *selected_rows, *node;
335         GtkTreePath *path;
336         GtkTreeRowReference *result;
337         GtkTreeModel *model;
338
339         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
340         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
341         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
342
343         if (selected_rows == NULL)
344                 return NULL;
345
346         node = g_list_last (selected_rows);
347         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
348         gtk_tree_path_next (path);
349
350         result = gtk_tree_row_reference_new (model, path);
351
352         gtk_tree_path_free (path);
353         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
354         g_list_free (selected_rows);
355
356         return result;
357 }
358
359 static void
360 headers_action_mark_as_read (TnyHeader *header,
361                              ModestWindow *win,
362                              gpointer user_data)
363 {
364         TnyHeaderFlags flags;
365
366         g_return_if_fail (TNY_IS_HEADER(header));
367
368         flags = tny_header_get_flags (header);
369         if (flags & TNY_HEADER_FLAG_SEEN) return;
370         tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
371 }
372
373 static void
374 headers_action_mark_as_unread (TnyHeader *header,
375                                ModestWindow *win,
376                                gpointer user_data)
377 {
378         TnyHeaderFlags flags;
379
380         g_return_if_fail (TNY_IS_HEADER(header));
381
382         flags = tny_header_get_flags (header);
383         if (flags & TNY_HEADER_FLAG_SEEN)  {
384                 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
385         }
386 }
387
388 /** After deleing a message that is currently visible in a window, 
389  * show the next message from the list, or close the window if there are no more messages.
390  **/
391 void 
392 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
393 {
394         /* Close msg view window or select next */
395         if (modest_msg_view_window_last_message_selected (win) &&
396                 modest_msg_view_window_first_message_selected (win)) {
397                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
398         } else if (!modest_msg_view_window_select_next_message (win)) {
399                 gboolean ret_value;
400                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);       
401         }
402 }
403
404
405 void
406 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
407 {
408         TnyList *header_list = NULL;
409         TnyIterator *iter = NULL;
410         TnyHeader *header = NULL;
411         gchar *message = NULL;
412         gchar *desc = NULL;
413         gint response;
414         ModestWindowMgr *mgr;
415         GtkWidget *header_view = NULL;
416
417         g_return_if_fail (MODEST_IS_WINDOW(win));
418         
419         /* Check first if the header view has the focus */
420         if (MODEST_IS_MAIN_WINDOW (win)) {
421                 header_view = 
422                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
423                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
424                 if (!gtk_widget_is_focus (header_view))
425                         return;
426         }
427         
428         /* Get the headers, either from the header view (if win is the main window),
429          * or from the message view window: */
430         header_list = get_selected_headers (win);
431         if (!header_list) return;
432                         
433         /* Check if any of the headers are already opened, or in the process of being opened */
434         if (MODEST_IS_MAIN_WINDOW (win)) {
435                 gint opened_headers = 0;
436
437                 iter = tny_list_create_iterator (header_list);
438                 mgr = modest_runtime_get_window_mgr ();
439                 while (!tny_iterator_is_done (iter)) {
440                         header = TNY_HEADER (tny_iterator_get_current (iter));
441                         if (header) {
442                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
443                                         opened_headers++;
444                                 g_object_unref (header);
445                         }
446                         tny_iterator_next (iter);
447                 }
448                 g_object_unref (iter);
449
450                 if (opened_headers > 0) {
451                         gchar *msg;
452
453                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), 
454                                                opened_headers);
455
456                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
457                         
458                         g_free (msg);
459                         g_object_unref (header_list);
460                         return;
461                 }
462         }
463
464         /* Select message */
465         if (tny_list_get_length(header_list) == 1) {
466                 iter = tny_list_create_iterator (header_list);
467                 header = TNY_HEADER (tny_iterator_get_current (iter));
468                 if (header) {
469                         desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
470                         g_object_unref (header);
471                 }
472
473                 g_object_unref (iter);
474         }
475         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
476                                            tny_list_get_length(header_list)), desc);
477
478         /* Confirmation dialog */
479         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
480                                                             message);
481         
482
483         if (response == GTK_RESPONSE_OK) {      
484                 ModestWindow *main_window = NULL;
485                 ModestWindowMgr *mgr = NULL;
486                 GtkTreeModel *model = NULL;
487                 GtkTreeSelection *sel = NULL;
488                 GList *sel_list = NULL, *tmp = NULL;
489                 GtkTreeRowReference *next_row_reference = NULL;
490                 GtkTreeRowReference *prev_row_reference = NULL;
491                 GtkTreePath *next_path = NULL;
492                 GtkTreePath *prev_path = NULL;
493                 ModestMailOperation *mail_op = NULL;
494
495                 /* Find last selected row */                    
496                 if (MODEST_IS_MAIN_WINDOW (win)) {
497                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
498                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
499                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
500                         for (tmp=sel_list; tmp; tmp=tmp->next) {
501                                 if (tmp->next == NULL) {
502                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
503                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
504
505                                         gtk_tree_path_prev (prev_path);
506                                         gtk_tree_path_next (next_path);
507
508                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
509                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
510                                 }
511                         }
512                 }
513                 
514                 /* Disable window dimming management */
515                 modest_window_disable_dimming (MODEST_WINDOW(win));
516
517                 /* Remove each header. If it's a view window header_view == NULL */
518                 mail_op = modest_mail_operation_new ((GObject *) win);
519                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
520                                                  mail_op);
521                 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
522                 g_object_unref (mail_op);
523                 
524                 /* Enable window dimming management */
525                 if (sel != NULL) {
526                         gtk_tree_selection_unselect_all (sel);
527                 }
528                 modest_window_enable_dimming (MODEST_WINDOW(win));
529                 
530                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
531                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
532                         
533                         /* Get main window */
534                         mgr = modest_runtime_get_window_mgr ();
535                         main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
536                 } else {                        
537                         /* Move cursor to next row */
538                         main_window = win; 
539
540                         /* Select next or previous row */
541                         if (gtk_tree_row_reference_valid (next_row_reference)) {
542 /*                              next_path = gtk_tree_row_reference_get_path (row_reference); */
543                                 gtk_tree_selection_select_path (sel, next_path);
544                         }
545                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {                           
546                                 gtk_tree_selection_select_path (sel, prev_path);
547                         }
548
549                         /* Free */
550                         if (next_row_reference != NULL) 
551                                 gtk_tree_row_reference_free (next_row_reference);
552                         if (next_path != NULL) 
553                                 gtk_tree_path_free (next_path);                         
554                         if (prev_row_reference != NULL) 
555                                 gtk_tree_row_reference_free (prev_row_reference);
556                         if (prev_path != NULL) 
557                                 gtk_tree_path_free (prev_path);                         
558                 }
559                 
560                 /* Update toolbar dimming state */
561                 if (main_window)
562                         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
563
564                 /* Free */
565                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
566                 g_list_free (sel_list);
567         }
568
569         /* Free*/
570         g_free(message);
571         g_free(desc);
572         g_object_unref (header_list);
573 }
574
575
576
577
578 /* delete either message or folder, based on where we are */
579 void
580 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
581 {
582         g_return_if_fail (MODEST_IS_WINDOW(win));
583         
584         /* Check first if the header view has the focus */
585         if (MODEST_IS_MAIN_WINDOW (win)) {
586                 GtkWidget *w;
587                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
588                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
589                 if (gtk_widget_is_focus (w)) {
590                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
591                         return;
592                 }
593         }
594         modest_ui_actions_on_delete_message (action, win);
595 }
596
597
598
599 void
600 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
601 {       
602         ModestWindowMgr *mgr = NULL;
603         
604 #ifdef MODEST_PLATFORM_MAEMO
605         modest_osso_save_state();
606 #endif /* MODEST_PLATFORM_MAEMO */
607
608         g_debug ("closing down, clearing %d item(s) from operation queue",
609                  modest_mail_operation_queue_num_elements
610                  (modest_runtime_get_mail_operation_queue()));
611
612         /* cancel all outstanding operations */
613         modest_mail_operation_queue_cancel_all 
614                 (modest_runtime_get_mail_operation_queue());
615         
616         g_debug ("queue has been cleared");
617
618
619         /* Check if there are opened editing windows */ 
620         mgr = modest_runtime_get_window_mgr ();
621         modest_window_mgr_close_all_windows (mgr);
622
623         /* note: when modest-tny-account-store is finalized,
624            it will automatically set all network connections
625            to offline */
626
627 /*      gtk_main_quit (); */
628 }
629
630 void
631 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
632 {
633         gboolean ret_value;
634
635         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
636
637 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
638 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
639 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
640 /*              gboolean ret_value; */
641 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
642 /*      } else if (MODEST_IS_WINDOW (win)) { */
643 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
644 /*      } else { */
645 /*              g_return_if_reached (); */
646 /*      } */
647 }
648
649 void
650 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
651 {
652         GtkClipboard *clipboard = NULL;
653         gchar *selection = NULL;
654
655         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
656         selection = gtk_clipboard_wait_for_text (clipboard);
657
658         /* Question: why is the clipboard being used here? 
659          * It doesn't really make a lot of sense. */
660
661         if (selection)
662         {
663                 modest_address_book_add_address (selection);
664                 g_free (selection);
665         }
666 }
667
668 void
669 modest_ui_actions_on_accounts (GtkAction *action, 
670                                ModestWindow *win)
671 {
672         /* This is currently only implemented for Maemo */
673         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
674                 if (!modest_ui_actions_run_account_setup_wizard (win)) 
675                         g_debug ("%s: wizard was already running", __FUNCTION__);
676                 
677                 return;
678         } else {
679                 /* Show the list of accounts */
680                 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
681                 gtk_window_set_transient_for (account_win, GTK_WINDOW (win));
682                 
683                 /* The accounts dialog must be modal */
684                 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), account_win);
685                 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win)); 
686         }
687 }
688
689 #ifdef MODEST_PLATFORM_MAEMO
690 static void
691 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
692 {
693         /* Save any changes. */
694         modest_connection_specific_smtp_window_save_server_accounts (
695                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
696         gtk_widget_destroy (GTK_WIDGET (window));
697 }
698 #endif
699
700
701 void
702 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
703 {
704         /* This is currently only implemented for Maemo,
705          * because it requires an API (libconic) to detect different connection 
706          * possiblities.
707          */
708 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
709         
710         /* Create the window if necessary: */
711         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
712         modest_connection_specific_smtp_window_fill_with_connections (
713                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
714                 modest_runtime_get_account_mgr());
715
716         /* Show the window: */  
717         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
718         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
719         gtk_widget_show (specific_window);
720     
721         /* Save changes when the window is hidden: */
722         g_signal_connect (specific_window, "hide", 
723                 G_CALLBACK (on_smtp_servers_window_hide), win);
724 #endif /* MODEST_PLATFORM_MAEMO */
725 }
726
727 void
728 modest_ui_actions_compose_msg(ModestWindow *win,
729                               const gchar *to_str,
730                               const gchar *cc_str,
731                               const gchar *bcc_str,
732                               const gchar *subject_str,
733                               const gchar *body_str,
734                               GSList *attachments)
735 {
736         gchar *account_name = NULL;
737         TnyMsg *msg = NULL;
738         TnyAccount *account = NULL;
739         TnyFolder *folder = NULL;
740         gchar *from_str = NULL, *signature = NULL, *body = NULL;
741         gboolean use_signature = FALSE;
742         ModestWindow *msg_win = NULL;
743         ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
744         ModestTnyAccountStore *store = modest_runtime_get_account_store();
745
746         account_name = modest_account_mgr_get_default_account(mgr);
747         if (!account_name) {
748                 g_printerr ("modest: no account found\n");
749                 goto cleanup;
750         }
751         account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
752         if (!account) {
753                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
754                 goto cleanup;
755         }
756         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
757         if (!folder) {
758                 g_printerr ("modest: failed to find Drafts folder\n");
759                 goto cleanup;
760         }
761         from_str = modest_account_mgr_get_from_string (mgr, account_name);
762         if (!from_str) {
763                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
764                 goto cleanup;
765         }
766
767         signature = modest_account_mgr_get_signature (mgr, account_name, &use_signature);
768         if (body_str != NULL) {
769                 body = use_signature ? g_strconcat(body_str, "\n", signature, NULL) : g_strdup(body_str);
770         } else {
771                 body = use_signature ? g_strconcat("\n", signature, NULL) : g_strdup("");
772         }
773
774         msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, body, NULL);
775         if (!msg) {
776                 g_printerr ("modest: failed to create new msg\n");
777                 goto cleanup;
778         }
779
780         /* Create and register edit window */
781         /* This is destroyed by TODO. */
782         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
783         while (attachments) {
784                 modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
785                                                        attachments->data);
786                 attachments = g_slist_next(attachments);
787         }
788         modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win);
789
790         if (win) {
791                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
792                                               GTK_WINDOW (win));
793         }
794         gtk_widget_show_all (GTK_WIDGET (msg_win));
795
796 cleanup:
797         g_free (from_str);
798         g_free (signature);
799         g_free (body);
800         g_free (account_name);
801         if (account) g_object_unref (G_OBJECT(account));
802         if (folder) g_object_unref (G_OBJECT(folder));
803         if (msg_win) g_object_unref (G_OBJECT(msg_win));
804         if (msg) g_object_unref (G_OBJECT(msg));
805 }
806
807 void
808 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
809 {
810         /* if there are no accounts yet, just show the wizard */
811         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
812                 if (!modest_ui_actions_run_account_setup_wizard (win))
813                         return;
814                 
815         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL);
816 }
817
818 gboolean 
819 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
820                                        TnyHeader *header,
821                                        TnyMsg *msg)
822 {
823         ModestMailOperationStatus status;
824
825         /* If there is no message or the operation was not successful */
826         status = modest_mail_operation_get_status (mail_op);
827         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
828
829                 /* Remove the header from the preregistered uids */
830                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
831                                                      header);
832
833                 return FALSE;
834         }
835
836         return TRUE;
837 }
838
839 static void
840 open_msg_cb (ModestMailOperation *mail_op, 
841              TnyHeader *header,  
842              gboolean canceled,
843              TnyMsg *msg, 
844              GError *err,
845              gpointer user_data)
846 {
847         ModestWindowMgr *mgr = NULL;
848         ModestWindow *parent_win = NULL;
849         ModestWindow *win = NULL;
850         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
851         gchar *account = NULL;
852         TnyFolder *folder;
853         gboolean open_in_editor = FALSE;
854         
855         /* Do nothing if there was any problem with the mail
856            operation. The error will be shown by the error_handler of
857            the mail operation */
858         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
859                 return;
860
861         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
862         folder = tny_header_get_folder (header);
863
864         /* Mark header as read */
865         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
866
867         /* Gets folder type (OUTBOX headers will be opened in edit window */
868         if (modest_tny_folder_is_local_folder (folder)) {
869                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
870                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
871                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
872         }
873
874                 
875         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
876                 TnyTransportAccount *traccount = NULL;
877                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
878                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
879                 if (traccount) {
880                         ModestTnySendQueue *send_queue = NULL;
881                         ModestTnySendQueueStatus status;
882                         char *msg_id;
883                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
884                                                    TNY_ACCOUNT(traccount)));
885                         send_queue = modest_runtime_get_send_queue(traccount);
886                         msg_id = modest_tny_send_queue_get_msg_id (header);
887                         status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
888                         /* Only open messages in outbox with the editor if they are in Failed state */
889                         if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
890                                 open_in_editor = TRUE;
891                         }
892                         g_free(msg_id);
893                         g_object_unref(traccount);
894                 } else {
895                         g_warning("Cannot get transport account for message in outbox!!");
896                 }
897         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
898                 open_in_editor = TRUE; /* Open in editor if the message is in the Drafts folder */
899         }
900
901         /* Get account */
902         if (!account)
903                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
904         if (!account)
905                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
906         
907         if (open_in_editor) {
908                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
909                 const gchar *from_header = NULL;
910
911                 from_header = tny_header_get_from (header);
912
913                 /* we cannot edit without a valid account... */
914                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
915                         if (!modest_ui_actions_run_account_setup_wizard(parent_win))
916                                 goto cleanup;
917                 }
918                 
919                 if (from_header) {
920                         GSList *accounts = modest_account_mgr_account_names (mgr, TRUE);
921                         GSList *node = NULL;
922                         for (node = accounts; node != NULL; node = g_slist_next (node)) {
923                                 gchar *from = modest_account_mgr_get_from_string (mgr, node->data);
924                                 
925                                 if (from && (strcmp (from_header, from) == 0)) {
926                                         g_free (account);
927                                         account = g_strdup (node->data);
928                                         g_free (from);
929                                         break;
930                                 }
931                                 g_free (from);
932                         }
933                         g_slist_foreach (accounts, (GFunc) g_free, NULL);
934                         g_slist_free (accounts);
935                 }
936
937                 win = modest_msg_edit_window_new (msg, account, TRUE);
938
939
940                 /* Show banner */
941                 modest_platform_information_banner_with_timeout
942                         (NULL, NULL, _("mail_ib_opening_draft_message"), 1200);
943
944         } else {
945                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
946                 
947                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
948                         GtkWidget *header_view;
949                         GtkTreeSelection *sel;
950                         GList *sel_list = NULL;
951                         GtkTreeModel *model;
952                         
953                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
954                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
955
956                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
957                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
958
959                         if (sel_list != NULL) {
960                                 GtkTreeRowReference *row_reference;
961
962                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
963                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
964                                 g_list_free (sel_list);
965                                 
966                                 win = modest_msg_view_window_new_with_header_model (
967                                                 msg, account, (const gchar*) uid,
968                                                 model, row_reference);
969                                 gtk_tree_row_reference_free (row_reference);
970                         } else {
971                                 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
972                         }
973                 } else {
974                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
975                 }
976                 g_free (uid);
977         }
978         
979         /* Register and show new window */
980         if (win != NULL) {
981                 mgr = modest_runtime_get_window_mgr ();
982                 modest_window_mgr_register_window (mgr, win);
983                 g_object_unref (win);
984                 gtk_widget_show_all (GTK_WIDGET(win));
985         }
986
987         /* Update toolbar dimming state */
988         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
989                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
990         }
991
992 cleanup:
993         /* Free */
994         g_free(account);
995         g_object_unref (parent_win);
996         g_object_unref (folder);
997 }
998
999 void
1000 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
1001                                                gpointer user_data)
1002 {
1003         const GError *error;
1004         GObject *win = NULL;
1005         const gchar *err_msg;
1006
1007         win = modest_mail_operation_get_source (mail_op);
1008         error = modest_mail_operation_get_error (mail_op);
1009  
1010         /* Select error message */
1011         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT)
1012                 err_msg = _("emev_ni_ui_imap_msg_size_exceed_error");
1013         else
1014                 err_msg = (const gchar *) user_data;
1015
1016         /* Show error */
1017         modest_platform_run_information_dialog ((GtkWindow *) win, err_msg);
1018
1019         if (win)
1020                 g_object_unref (win);
1021 }
1022
1023 /**
1024  * Returns the account a list of headers belongs to. It returns a
1025  * *new* reference so don't forget to unref it
1026  */
1027 static TnyAccount*
1028 get_account_from_header_list (TnyList *headers)
1029 {
1030         TnyAccount *account = NULL;
1031
1032         if (tny_list_get_length (headers) > 0) {
1033                 TnyIterator *iter = tny_list_create_iterator (headers);
1034                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1035                 TnyFolder *folder = tny_header_get_folder (header);
1036                 account = tny_folder_get_account (folder);
1037                 g_object_unref (folder);
1038                 g_object_unref (header);
1039                 g_object_unref (iter);
1040         }
1041         return account;
1042 }
1043
1044 static void
1045 open_msgs_performer(gboolean canceled, 
1046                     GError *err,
1047                     GtkWindow *parent_window,
1048                     TnyAccount *account,
1049                     gpointer user_data)
1050 {
1051         ModestMailOperation *mail_op = NULL;
1052         const gchar *proto_name;
1053         gchar *error_msg;
1054         ModestTransportStoreProtocol proto;
1055         TnyList *not_opened_headers;
1056         TnyConnectionStatus status;
1057
1058         not_opened_headers = TNY_LIST (user_data);
1059
1060         status = tny_account_get_connection_status (account);
1061         if (err || canceled) {
1062                 /* TODO: Show an error ? */
1063                 goto clean;
1064         }
1065
1066         /* Get the error message depending on the protocol */
1067         proto_name = tny_account_get_proto (account);
1068         if (proto_name != NULL) {
1069                 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
1070         } else {
1071                 proto = MODEST_PROTOCOL_STORE_MAILDIR;
1072         }
1073         
1074         /* Create the error messages */
1075         if (tny_list_get_length (not_opened_headers) == 1) {
1076                 if (proto == MODEST_PROTOCOL_STORE_POP) {
1077                         error_msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
1078                 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
1079                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1080                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1081                         error_msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
1082                                                      tny_header_get_subject (header));
1083                         g_object_unref (header);
1084                         g_object_unref (iter);
1085                 } else {
1086                         error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1087                 }
1088         } else {
1089                 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1090         }
1091
1092         /* Create the mail operation */
1093         mail_op = 
1094                 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1095                                                                modest_ui_actions_get_msgs_full_error_handler,
1096                                                                error_msg, g_free);
1097         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1098                                          mail_op);
1099                 
1100         modest_mail_operation_get_msgs_full (mail_op,
1101                                              not_opened_headers,
1102                                              open_msg_cb,
1103                                              NULL,
1104                                              NULL);
1105
1106         /* Frees */
1107  clean:
1108         if (mail_op)
1109                 g_object_unref (mail_op);
1110         g_object_unref (not_opened_headers);
1111         g_object_unref (account);
1112 }
1113
1114 /*
1115  * This function is used by both modest_ui_actions_on_open and
1116  * modest_ui_actions_on_header_activated. This way we always do the
1117  * same when trying to open messages.
1118  */
1119 static void
1120 open_msgs_from_headers (TnyList *headers, ModestWindow *win)
1121 {
1122         ModestWindowMgr *mgr = NULL;
1123         TnyIterator *iter = NULL, *iter_not_opened = NULL;
1124         TnyList *not_opened_headers = NULL;
1125         TnyHeaderFlags flags = 0;
1126         TnyAccount *account;
1127         gint uncached_msgs = 0;
1128                 
1129         g_return_if_fail (headers != NULL);
1130
1131         /* Check that only one message is selected for opening */
1132         if (tny_list_get_length (headers) != 1) {
1133                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1134                                                         _("mcen_ib_select_one_message"));
1135                 return;
1136         }
1137
1138         mgr = modest_runtime_get_window_mgr ();
1139         iter = tny_list_create_iterator (headers);
1140
1141         /* Get the account */
1142         account = get_account_from_header_list (headers);
1143         
1144         /* Look if we already have a message view for each header. If
1145            true, then remove the header from the list of headers to
1146            open */
1147         not_opened_headers = tny_simple_list_new ();
1148         while (!tny_iterator_is_done (iter)) {
1149
1150                 ModestWindow *window = NULL;
1151                 TnyHeader *header = NULL;
1152                 gboolean found = FALSE;
1153                 
1154                 header = TNY_HEADER (tny_iterator_get_current (iter));
1155                 if (header)
1156                         flags = tny_header_get_flags (header);
1157
1158                 window = NULL;
1159                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1160                 
1161                 /* Do not open again the message and present the
1162                    window to the user */
1163                 if (found) {
1164                         if (window)
1165                                 gtk_window_present (GTK_WINDOW (window));
1166                         else
1167                                 /* the header has been registered already, we don't do
1168                                  * anything but wait for the window to come up*/
1169                                 g_debug ("header %p already registered, waiting for window", header);
1170                 } else {
1171                         tny_list_append (not_opened_headers, G_OBJECT (header));
1172                 }
1173
1174                 if (header)
1175                         g_object_unref (header);
1176
1177                 tny_iterator_next (iter);
1178         }
1179         g_object_unref (iter);
1180         iter = NULL;
1181
1182         /* Open each message */
1183         if (tny_list_get_length (not_opened_headers) == 0)
1184                 goto cleanup;
1185         
1186         /* If some messages would have to be downloaded, ask the user to 
1187          * make a connection. It's generally easier to do this here (in the mainloop) 
1188          * than later in a thread:
1189          */
1190         if (tny_list_get_length (not_opened_headers) > 0) {
1191                 uncached_msgs = header_list_count_uncached_msgs (not_opened_headers);
1192
1193                 if (uncached_msgs > 0) {
1194                         /* Allways download if we are online. */
1195                         if (!tny_device_is_online (modest_runtime_get_device ())) {
1196                                 gint response;
1197
1198                                 /* If ask for user permission to download the messages */
1199                                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1200                                                                                     ngettext("mcen_nc_get_msg",
1201                                                                                              "mcen_nc_get_msgs",
1202                                                                                              uncached_msgs));
1203
1204                                 /* End if the user does not want to continue */
1205                                 if (response == GTK_RESPONSE_CANCEL)
1206                                         goto cleanup;
1207                         }
1208                 }
1209         }
1210         
1211         /* Register the headers before actually creating the windows: */
1212         iter_not_opened = tny_list_create_iterator (not_opened_headers);
1213         while (!tny_iterator_is_done (iter_not_opened)) {
1214                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1215                 if (header) {
1216                         modest_window_mgr_register_header (mgr, header, NULL);
1217                         g_object_unref (header);
1218                 }
1219                 tny_iterator_next (iter_not_opened);
1220         }
1221         g_object_unref (iter_not_opened);
1222         iter_not_opened = NULL;
1223
1224         /* Connect to the account and perform */
1225         if (uncached_msgs > 0) {
1226                 modest_platform_connect_and_perform ((GtkWindow *) win, g_object_ref (account), 
1227                                                      open_msgs_performer, g_object_ref (not_opened_headers));
1228         } else {
1229                 /* Call directly the performer, do not need to connect */
1230                 open_msgs_performer (FALSE, NULL, (GtkWindow *) win, g_object_ref (account),
1231                                      g_object_ref (not_opened_headers));
1232         }
1233 cleanup:
1234         /* Clean */
1235         if (account)
1236                 g_object_unref (account);
1237         if (not_opened_headers)
1238                 g_object_unref (not_opened_headers);
1239 }
1240
1241 void
1242 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1243 {
1244         TnyList *headers;
1245
1246         /* Get headers */
1247         headers = get_selected_headers (win);
1248         if (!headers)
1249                 return;
1250
1251         /* Open them */
1252         open_msgs_from_headers (headers, win);
1253
1254         g_object_unref(headers);
1255 }
1256
1257
1258 static void
1259 free_reply_forward_helper (gpointer data)
1260 {
1261         ReplyForwardHelper *helper;
1262
1263         helper = (ReplyForwardHelper *) data;
1264         g_free (helper->account_name);
1265         g_slice_free (ReplyForwardHelper, helper);
1266 }
1267
1268 static void
1269 reply_forward_cb (ModestMailOperation *mail_op,  
1270                   TnyHeader *header, 
1271                   gboolean canceled,
1272                   TnyMsg *msg,
1273                   GError *err,
1274                   gpointer user_data)
1275 {
1276         TnyMsg *new_msg;
1277         ReplyForwardHelper *rf_helper;
1278         ModestWindow *msg_win = NULL;
1279         ModestEditType edit_type;
1280         gchar *from = NULL;
1281         TnyAccount *account = NULL;
1282         ModestWindowMgr *mgr = NULL;
1283         gchar *signature = NULL;
1284         gboolean use_signature;
1285
1286         /* If there was any error. The mail operation could be NULL,
1287            this means that we already have the message downloaded and
1288            that we didn't do a mail operation to retrieve it */
1289         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1290                 return;
1291                         
1292         g_return_if_fail (user_data != NULL);
1293         rf_helper = (ReplyForwardHelper *) user_data;
1294
1295         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1296                                                    rf_helper->account_name);
1297         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(), 
1298                                                       rf_helper->account_name, 
1299                                                       &use_signature);
1300
1301         /* Create reply mail */
1302         switch (rf_helper->action) {
1303         case ACTION_REPLY:
1304                 new_msg = 
1305                         modest_tny_msg_create_reply_msg (msg, header, from, signature,
1306                                                          rf_helper->reply_forward_type,
1307                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1308                 break;
1309         case ACTION_REPLY_TO_ALL:
1310                 new_msg = 
1311                         modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1312                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1313                 edit_type = MODEST_EDIT_TYPE_REPLY;
1314                 break;
1315         case ACTION_FORWARD:
1316                 new_msg = 
1317                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1318                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1319                 break;
1320         default:
1321                 g_return_if_reached ();
1322                 return;
1323         }
1324
1325         g_free (signature);
1326
1327         if (!new_msg) {
1328                 g_printerr ("modest: failed to create message\n");
1329                 goto cleanup;
1330         }
1331
1332         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1333                                                                        rf_helper->account_name,
1334                                                                        TNY_ACCOUNT_TYPE_STORE);
1335         if (!account) {
1336                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1337                 goto cleanup;
1338         }
1339
1340         /* Create and register the windows */
1341         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1342         mgr = modest_runtime_get_window_mgr ();
1343         modest_window_mgr_register_window (mgr, msg_win);
1344
1345         if (rf_helper->parent_window != NULL) {
1346                 gdouble parent_zoom;
1347
1348                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1349                 modest_window_set_zoom (msg_win, parent_zoom);
1350         }
1351
1352         /* Show edit window */
1353         gtk_widget_show_all (GTK_WIDGET (msg_win));
1354
1355 cleanup:
1356         if (msg_win)
1357                 g_object_unref (msg_win);
1358         if (new_msg)
1359                 g_object_unref (G_OBJECT (new_msg));
1360         if (account)
1361                 g_object_unref (G_OBJECT (account));
1362 /*      g_object_unref (msg); */
1363         free_reply_forward_helper (rf_helper);
1364 }
1365
1366 /* Checks a list of headers. If any of them are not currently
1367  * downloaded (CACHED) then returns TRUE else returns FALSE.
1368  */
1369 static gint
1370 header_list_count_uncached_msgs (TnyList *header_list)
1371 {
1372         TnyIterator *iter;
1373         gint uncached_messages = 0;
1374
1375         iter = tny_list_create_iterator (header_list);
1376         while (!tny_iterator_is_done (iter)) {
1377                 TnyHeader *header;
1378
1379                 header = TNY_HEADER (tny_iterator_get_current (iter));
1380                 if (header) {
1381                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1382                                 uncached_messages ++;
1383                         g_object_unref (header);
1384                 }
1385
1386                 tny_iterator_next (iter);
1387         }
1388         g_object_unref (iter);
1389
1390         return uncached_messages;
1391 }
1392
1393 /* Returns FALSE if the user does not want to download the
1394  * messages. Returns TRUE if the user allowed the download.
1395  */
1396 static gboolean
1397 connect_to_get_msg (ModestWindow *win,
1398                     gint num_of_uncached_msgs,
1399                     TnyAccount *account)
1400 {
1401         GtkResponseType response;
1402
1403         /* Allways download if we are online. */
1404         if (tny_device_is_online (modest_runtime_get_device ()))
1405                 return TRUE;
1406
1407         /* If offline, then ask for user permission to download the messages */
1408         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1409                         ngettext("mcen_nc_get_msg",
1410                         "mcen_nc_get_msgs",
1411                         num_of_uncached_msgs));
1412
1413         if (response == GTK_RESPONSE_CANCEL)
1414                 return FALSE;
1415
1416         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1417 }
1418
1419 /*
1420  * Common code for the reply and forward actions
1421  */
1422 static void
1423 reply_forward (ReplyForwardAction action, ModestWindow *win)
1424 {
1425         ModestMailOperation *mail_op = NULL;
1426         TnyList *header_list = NULL;
1427         ReplyForwardHelper *rf_helper = NULL;
1428         guint reply_forward_type;
1429         gboolean continue_download = TRUE;
1430         gboolean do_retrieve = TRUE;
1431         
1432         g_return_if_fail (MODEST_IS_WINDOW(win));
1433
1434         /* we need an account when editing */
1435         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1436                 if (!modest_ui_actions_run_account_setup_wizard (win))
1437                         return;
1438         }
1439         
1440         header_list = get_selected_headers (win);
1441         if (!header_list)
1442                 return;
1443
1444         reply_forward_type = 
1445                 modest_conf_get_int (modest_runtime_get_conf (),
1446                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1447                                      NULL);
1448
1449         /* check if we need to download msg before asking about it */
1450         do_retrieve = (action == ACTION_FORWARD) ||
1451                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1452
1453         if (do_retrieve){
1454                 gint num_of_unc_msgs;
1455
1456                 /* check that the messages have been previously downloaded */
1457                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1458                 /* If there are any uncached message ask the user
1459                  * whether he/she wants to download them. */
1460                 if (num_of_unc_msgs) {
1461                         TnyAccount *account = get_account_from_header_list (header_list);
1462                         continue_download = connect_to_get_msg (win, num_of_unc_msgs, account);
1463                         g_object_unref (account);
1464                 }
1465         }
1466
1467         if (!continue_download) {
1468                 g_object_unref (header_list);
1469                 return;
1470         }
1471         
1472         /* We assume that we can only select messages of the
1473            same folder and that we reply all of them from the
1474            same account. In fact the interface currently only
1475            allows single selection */
1476         
1477         /* Fill helpers */
1478         rf_helper = g_slice_new0 (ReplyForwardHelper);
1479         rf_helper->reply_forward_type = reply_forward_type;
1480         rf_helper->action = action;
1481         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1482         
1483         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1484                 rf_helper->parent_window = GTK_WIDGET (win);
1485         if (!rf_helper->account_name)
1486                 rf_helper->account_name =
1487                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1488
1489         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1490                 TnyMsg *msg;
1491                 TnyHeader *header;
1492                 /* Get header and message. Do not free them here, the
1493                    reply_forward_cb must do it */
1494                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1495                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1496                 if (!msg || !header) {
1497                         if (msg)
1498                                 g_object_unref (msg);
1499                         g_printerr ("modest: no message found\n");
1500                         return;
1501                 } else {
1502                         reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1503                 }
1504                 if (header)
1505                         g_object_unref (header);
1506         } else {
1507                 TnyHeader *header;
1508                 TnyIterator *iter;
1509
1510                 /* Only reply/forward to one message */
1511                 iter = tny_list_create_iterator (header_list);
1512                 header = TNY_HEADER (tny_iterator_get_current (iter));
1513                 g_object_unref (iter);
1514
1515                 if (header) {
1516                         /* Retrieve messages */
1517                         if (do_retrieve) {
1518                                 mail_op = 
1519                                         modest_mail_operation_new_with_error_handling (G_OBJECT(win),
1520                                                                                        modest_ui_actions_get_msgs_full_error_handler, 
1521                                                                                        NULL, NULL);
1522                                 modest_mail_operation_queue_add (
1523                                         modest_runtime_get_mail_operation_queue (), mail_op);
1524                                 
1525                                 modest_mail_operation_get_msg (mail_op,
1526                                                                header,
1527                                                                reply_forward_cb,
1528                                                                rf_helper);
1529                                 /* Clean */
1530                                 g_object_unref(mail_op);
1531                         } else {
1532                                 /* we put a ref here to prevent double unref as the reply
1533                                  * forward callback unrefs the header at its end */
1534                                 reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
1535                         }
1536
1537
1538                         g_object_unref (header);
1539                 }
1540
1541         }
1542
1543         /* Free */
1544         g_object_unref (header_list);
1545 }
1546
1547 void
1548 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1549 {
1550         g_return_if_fail (MODEST_IS_WINDOW(win));
1551
1552         reply_forward (ACTION_REPLY, win);
1553 }
1554
1555 void
1556 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1557 {
1558         g_return_if_fail (MODEST_IS_WINDOW(win));
1559
1560         reply_forward (ACTION_FORWARD, win);
1561 }
1562
1563 void
1564 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1565 {
1566         g_return_if_fail (MODEST_IS_WINDOW(win));
1567
1568         reply_forward (ACTION_REPLY_TO_ALL, win);
1569 }
1570
1571 void 
1572 modest_ui_actions_on_next (GtkAction *action, 
1573                            ModestWindow *window)
1574 {
1575         if (MODEST_IS_MAIN_WINDOW (window)) {
1576                 GtkWidget *header_view;
1577
1578                 header_view = modest_main_window_get_child_widget (
1579                                 MODEST_MAIN_WINDOW(window),
1580                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1581                 if (!header_view)
1582                         return;
1583         
1584                 modest_header_view_select_next (
1585                                 MODEST_HEADER_VIEW(header_view)); 
1586         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1587                 modest_msg_view_window_select_next_message (
1588                                 MODEST_MSG_VIEW_WINDOW (window));
1589         } else {
1590                 g_return_if_reached ();
1591         }
1592 }
1593
1594 void 
1595 modest_ui_actions_on_prev (GtkAction *action, 
1596                            ModestWindow *window)
1597 {
1598         g_return_if_fail (MODEST_IS_WINDOW(window));
1599
1600         if (MODEST_IS_MAIN_WINDOW (window)) {
1601                 GtkWidget *header_view;
1602                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1603                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1604                 if (!header_view)
1605                         return;
1606                 
1607                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1608         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1609                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1610         } else {
1611                 g_return_if_reached ();
1612         }
1613 }
1614
1615 void 
1616 modest_ui_actions_on_sort (GtkAction *action, 
1617                            ModestWindow *window)
1618 {
1619         g_return_if_fail (MODEST_IS_WINDOW(window));
1620
1621         if (MODEST_IS_MAIN_WINDOW (window)) {
1622                 GtkWidget *header_view;
1623                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1624                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1625                 if (!header_view) {
1626                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1627
1628                         return;
1629                 }
1630
1631                 /* Show sorting dialog */
1632                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1633         }
1634 }
1635
1636 static void
1637 new_messages_arrived (ModestMailOperation *self, 
1638                       TnyList *new_headers,
1639                       gpointer user_data)
1640 {
1641         GObject *source;
1642
1643         source = modest_mail_operation_get_source (self);
1644
1645         /* Notify new messages have been downloaded. Do not notify if
1646            the send&receive was invoked by the user, i.e, if the mail
1647            operation has a source (the main window) */
1648         if ((new_headers != NULL) && (tny_list_get_length (new_headers) > 0) && !source)
1649                 modest_platform_on_new_headers_received (new_headers);
1650
1651         if (source)
1652                 g_object_unref (source);
1653 }
1654
1655 gboolean
1656 retrieve_all_messages_cb (GObject *source,
1657                           guint num_msgs,
1658                           guint retrieve_limit)
1659 {
1660         GtkWindow *window;
1661         gchar *msg;
1662         gint response;
1663
1664         window = GTK_WINDOW (source);
1665         msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"), 
1666                                num_msgs, retrieve_limit);
1667
1668         /* Ask the user if they want to retrieve all the messages */
1669         response = 
1670                 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
1671                                                                       _("mcen_bd_get_all"),
1672                                                                       _("mcen_bd_newest_only"));
1673         /* Free and return */
1674         g_free (msg);
1675         return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
1676 }
1677
1678 typedef struct {
1679         TnyAccount *account;
1680         ModestWindow *win;
1681         gchar *account_name;
1682 } SendReceiveInfo;
1683
1684 static void
1685 do_send_receive_performer (gboolean canceled, 
1686                            GError *err,
1687                            GtkWindow *parent_window, 
1688                            TnyAccount *account, 
1689                            gpointer user_data)
1690 {
1691         ModestMailOperation *mail_op;
1692         SendReceiveInfo *info;
1693
1694         info = (SendReceiveInfo *) user_data;
1695
1696         if (err || canceled) {
1697
1698                 goto clean;
1699         }
1700
1701         /* Set send/receive operation in progress */    
1702         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
1703                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
1704         }
1705         
1706         mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
1707                                                                  modest_ui_actions_send_receive_error_handler,
1708                                                                  NULL, NULL);
1709
1710         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
1711                 g_signal_connect (G_OBJECT(mail_op), "operation-finished", 
1712                                   G_CALLBACK (on_send_receive_finished), 
1713                                   info->win);
1714
1715         /* Send & receive. */
1716         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1717         modest_mail_operation_update_account (mail_op, info->account_name, (info->win) ? FALSE : TRUE,
1718                                               (info->win) ? retrieve_all_messages_cb : NULL, 
1719                                               new_messages_arrived, info->win);
1720         g_object_unref (G_OBJECT (mail_op));
1721         
1722  clean:
1723         /* Frees */
1724         if (info->account_name)
1725                 g_free (info->account_name);
1726         if (info->win)
1727                 g_object_unref (info->win);
1728         if (info->account)
1729                 g_object_unref (info->account);
1730         g_slice_free (SendReceiveInfo, info);
1731 }
1732
1733 /*
1734  * This function performs the send & receive required actions. The
1735  * window is used to create the mail operation. Typically it should
1736  * always be the main window, but we pass it as argument in order to
1737  * be more flexible.
1738  */
1739 void
1740 modest_ui_actions_do_send_receive (const gchar *account_name, 
1741                                    ModestWindow *win)
1742 {
1743         gchar *acc_name = NULL;
1744         SendReceiveInfo *info;
1745         ModestTnyAccountStore *acc_store;
1746
1747         /* If no account name was provided then get the current account, and if
1748            there is no current account then pick the default one: */
1749         if (!account_name) {
1750                 if (win)
1751                         acc_name = g_strdup (modest_window_get_active_account (win));
1752                 if (!acc_name)
1753                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1754                 if (!acc_name) {
1755                         g_printerr ("modest: cannot get default account\n");
1756                         return;
1757                 }
1758         } else {
1759                 acc_name = g_strdup (account_name);
1760         }
1761
1762         acc_store = modest_runtime_get_account_store ();
1763
1764         /* Create the info for the connect and perform */
1765         info = g_slice_new (SendReceiveInfo);
1766         info->account_name = acc_name;
1767         info->win = (win) ? g_object_ref (win) : NULL;
1768         info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
1769                                                                      TNY_ACCOUNT_TYPE_STORE);
1770
1771         /* Invoke the connect and perform */
1772         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL, info->account, 
1773                                              do_send_receive_performer, info);
1774 }
1775
1776
1777 static void
1778 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1779                                   ModestWindow *win)
1780 {
1781         TnyTransportAccount *transport_account;
1782         TnySendQueue *send_queue = NULL;
1783         GError *error = NULL;
1784
1785         /* Get transport account */
1786         transport_account =
1787                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1788                                       (modest_runtime_get_account_store(),
1789                                        account_name,
1790                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1791         if (!transport_account) {
1792                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1793                 goto frees;
1794         }
1795
1796         /* Get send queue*/
1797         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1798         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1799                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1800                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1801                              "modest: could not find send queue for account\n");
1802         } else {
1803                 /* Keeep messages in outbox folder */
1804                 tny_send_queue_cancel (send_queue, FALSE, &error);
1805         }       
1806
1807  frees:
1808         if (transport_account != NULL) 
1809                 g_object_unref (G_OBJECT (transport_account));
1810 }
1811
1812 static void
1813 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1814 {
1815         GSList *account_names, *iter;
1816
1817         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1818                                                           TRUE);
1819
1820         iter = account_names;
1821         while (iter) {                  
1822                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1823                 iter = g_slist_next (iter);
1824         }
1825
1826         modest_account_mgr_free_account_names (account_names);
1827         account_names = NULL;
1828 }
1829
1830 void
1831 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1832
1833 {
1834         /* Check if accounts exist */
1835         gboolean accounts_exist = 
1836                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1837         
1838         /* If not, allow the user to create an account before trying to send/receive. */
1839         if (!accounts_exist)
1840                 modest_ui_actions_on_accounts (NULL, win);
1841         
1842         /* Cancel all sending operaitons */     
1843         modest_ui_actions_cancel_send_all (win);
1844 }
1845
1846 /*
1847  * Refreshes all accounts. This function will be used by automatic
1848  * updates
1849  */
1850 void
1851 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1852 {
1853         GSList *account_names, *iter;
1854
1855         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1856                                                           TRUE);
1857
1858         iter = account_names;
1859         while (iter) {                  
1860                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1861                 iter = g_slist_next (iter);
1862         }
1863
1864         modest_account_mgr_free_account_names (account_names);
1865         account_names = NULL;
1866 }
1867
1868 /*
1869  * Handler of the click on Send&Receive button in the main toolbar
1870  */
1871 void
1872 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1873 {
1874         /* Check if accounts exist */
1875         gboolean accounts_exist;
1876
1877         accounts_exist =
1878                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1879         
1880         /* If not, allow the user to create an account before trying to send/receive. */
1881         if (!accounts_exist)
1882                 modest_ui_actions_on_accounts (NULL, win);
1883         
1884         /* Refresh the current folder. The if is always TRUE it's just an extra check */
1885         if (MODEST_IS_MAIN_WINDOW (win)) {
1886                 GtkWidget *folder_view;
1887                 TnyFolderStore *folder_store;
1888
1889                 folder_view = 
1890                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1891                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1892                 if (!folder_view)
1893                         return;
1894                 
1895                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1896         
1897                 if (folder_store)
1898                         g_object_unref (folder_store);
1899         }       
1900         
1901         /* Refresh the active account */
1902         modest_ui_actions_do_send_receive (NULL, win);
1903 }
1904
1905
1906 void
1907 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1908 {
1909         ModestConf *conf;
1910         GtkWidget *header_view;
1911         
1912         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1913
1914         header_view = modest_main_window_get_child_widget (main_window,
1915                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1916         if (!header_view)
1917                 return;
1918
1919         conf = modest_runtime_get_conf ();
1920         
1921         /* what is saved/restored is depending on the style; thus; we save with
1922          * old style, then update the style, and restore for this new style
1923          */
1924         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1925         
1926         if (modest_header_view_get_style
1927             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1928                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1929                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1930         else
1931                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1932                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1933
1934         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1935                                       MODEST_CONF_HEADER_VIEW_KEY);
1936 }
1937
1938
1939 void 
1940 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1941                                       TnyHeader *header,
1942                                       ModestMainWindow *main_window)
1943 {
1944         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1945         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1946         
1947         /* in the case the folder is empty, show the empty folder message and focus
1948          * folder view */
1949         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1950                 if (modest_header_view_is_empty (header_view)) {
1951                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1952                         GtkWidget *folder_view = 
1953                                 modest_main_window_get_child_widget (main_window,
1954                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1955                         if (folder != NULL) 
1956                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1957                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1958                         return;
1959                 }
1960         }
1961         /* If no header has been selected then exit */
1962         if (!header)
1963                 return;
1964
1965         /* Update focus */
1966         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1967             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1968
1969         /* Update toolbar dimming state */
1970         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1971 }
1972
1973 void
1974 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1975                                        TnyHeader *header,
1976                                        ModestMainWindow *main_window)
1977 {
1978         TnyList *headers;
1979
1980         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1981
1982         if (!header)
1983                 return;
1984
1985         if (modest_header_view_count_selected_headers (header_view) > 1) {
1986                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
1987                 return;
1988         }
1989
1990
1991 /*      headers = tny_simple_list_new (); */
1992 /*      tny_list_prepend (headers, G_OBJECT (header)); */
1993         headers = modest_header_view_get_selected_headers (header_view);
1994
1995         open_msgs_from_headers (headers, MODEST_WINDOW (main_window));
1996
1997         g_object_unref (headers);
1998 }
1999
2000 static void
2001 set_active_account_from_tny_account (TnyAccount *account,
2002                                      ModestWindow *window)
2003 {
2004         const gchar *server_acc_name = tny_account_get_id (account);
2005         
2006         /* We need the TnyAccount provided by the
2007            account store because that is the one that
2008            knows the name of the Modest account */
2009         TnyAccount *modest_server_account = modest_server_account = 
2010                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2011                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
2012                                                              server_acc_name);
2013         if (!modest_server_account) {
2014                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2015                 return;
2016         }
2017
2018         /* Update active account, but only if it's not a pseudo-account */
2019         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2020             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2021                 const gchar *modest_acc_name = 
2022                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2023                 if (modest_acc_name)
2024                         modest_window_set_active_account (window, modest_acc_name);
2025         }
2026         
2027         g_object_unref (modest_server_account);
2028 }
2029
2030
2031 static void
2032 folder_refreshed_cb (ModestMailOperation *mail_op, 
2033                      TnyFolder *folder, 
2034                      gpointer user_data)
2035 {
2036         ModestMainWindow *win = NULL;
2037         GtkWidget *header_view;
2038         gboolean folder_empty = FALSE;
2039         gboolean all_marked_as_deleted = FALSE;
2040
2041         g_return_if_fail (TNY_IS_FOLDER (folder));
2042
2043         win = MODEST_MAIN_WINDOW (user_data);
2044         header_view = 
2045                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2046
2047         if (header_view) {
2048                 TnyFolder *current_folder;
2049
2050                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2051                 if (current_folder != NULL && folder != current_folder) {
2052                         g_object_unref (current_folder);
2053                         return;
2054                 }
2055                 g_object_unref (current_folder);
2056         }
2057
2058         /* Check if folder is empty and set headers view contents style */
2059         folder_empty = (tny_folder_get_all_count (folder) == 0);
2060         all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
2061         if (folder_empty || all_marked_as_deleted)
2062                 modest_main_window_set_contents_style (win,
2063                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2064 }
2065
2066 void 
2067 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2068                                                TnyFolderStore *folder_store, 
2069                                                gboolean selected,
2070                                                ModestMainWindow *main_window)
2071 {
2072         ModestConf *conf;
2073         GtkWidget *header_view;
2074
2075         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2076
2077         header_view = modest_main_window_get_child_widget(main_window,
2078                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2079         if (!header_view)
2080                 return;
2081         
2082         conf = modest_runtime_get_conf ();
2083
2084         if (TNY_IS_ACCOUNT (folder_store)) {
2085                 if (selected) {
2086                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2087                         
2088                         /* Show account details */
2089                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2090                 }
2091         } else {
2092                 if (TNY_IS_FOLDER (folder_store) && selected) {
2093                         
2094                         /* Update the active account */
2095                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2096                         if (account) {
2097                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2098                                 g_object_unref (account);
2099                                 account = NULL;
2100                         }
2101
2102                         /* Set the header style by default, it could
2103                            be changed later by the refresh callback to
2104                            empty */
2105                         modest_main_window_set_contents_style (main_window, 
2106                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2107
2108                         /* Set folder on header view. This function
2109                            will call tny_folder_refresh_async so we
2110                            pass a callback that will be called when
2111                            finished. We use that callback to set the
2112                            empty view if there are no messages */
2113                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2114                                                        TNY_FOLDER (folder_store),
2115                                                        folder_refreshed_cb,
2116                                                        main_window);
2117                         
2118                         /* Restore configuration. We need to do this
2119                            *after* the set_folder because the widget
2120                            memory asks the header view about its
2121                            folder  */
2122                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2123                                                       G_OBJECT(header_view),
2124                                                       MODEST_CONF_HEADER_VIEW_KEY);
2125                 } else {
2126                         /* Update the active account */
2127                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2128                         /* Save only if we're seeing headers */
2129                         if (modest_main_window_get_contents_style (main_window) ==
2130                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2131                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2132                                                            MODEST_CONF_HEADER_VIEW_KEY);
2133                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2134                 }
2135         }
2136
2137         /* Update toolbar dimming state */
2138         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2139 }
2140
2141 void 
2142 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2143                                      ModestWindow *win)
2144 {
2145         GtkWidget *dialog;
2146         gchar *txt, *item;
2147         gboolean online;
2148
2149         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2150         
2151         online = tny_device_is_online (modest_runtime_get_device());
2152
2153         if (online) {
2154                 /* already online -- the item is simply not there... */
2155                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2156                                                  GTK_DIALOG_MODAL,
2157                                                  GTK_MESSAGE_WARNING,
2158                                                  GTK_BUTTONS_NONE,
2159                                                  _("The %s you selected cannot be found"),
2160                                                  item);
2161                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2162                 gtk_dialog_run (GTK_DIALOG(dialog));
2163         } else {
2164                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2165                                                       GTK_WINDOW (win),
2166                                                       GTK_DIALOG_MODAL,
2167                                                       _("mcen_bd_dialog_cancel"),
2168                                                       GTK_RESPONSE_REJECT,
2169                                                       _("mcen_bd_dialog_ok"),
2170                                                       GTK_RESPONSE_ACCEPT,
2171                                                       NULL);
2172                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2173                                          "Do you want to get online?"), item);
2174                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2175                                     gtk_label_new (txt), FALSE, FALSE, 0);
2176                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2177                 g_free (txt);
2178
2179                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2180                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2181                         /* TODO: Comment about why is this commented out: */
2182                         /* modest_platform_connect_and_wait (); */
2183                 }
2184         }
2185         gtk_widget_destroy (dialog);
2186 }
2187
2188 void
2189 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2190                                      ModestWindow *win)
2191 {
2192         /* g_message ("%s %s", __FUNCTION__, link); */
2193 }       
2194
2195
2196 void
2197 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2198                                         ModestWindow *win)
2199 {
2200         modest_platform_activate_uri (link);
2201 }
2202
2203 void
2204 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2205                                           ModestWindow *win)
2206 {
2207         modest_platform_show_uri_popup (link);
2208 }
2209
2210 void
2211 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2212                                              ModestWindow *win)
2213 {
2214         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2215 }
2216
2217 void
2218 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2219                                           const gchar *address,
2220                                           ModestWindow *win)
2221 {
2222         /* g_message ("%s %s", __FUNCTION__, address); */
2223 }
2224
2225 static void
2226 on_save_to_drafts_cb (ModestMailOperation *mail_op, 
2227                       TnyMsg *saved_draft,
2228                       gpointer user_data)
2229 {
2230         ModestMsgEditWindow *edit_window;
2231         ModestMainWindow *win;
2232
2233         /* FIXME. Make the header view sensitive again. This is a
2234          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2235          * for details */
2236         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2237                                          modest_runtime_get_window_mgr(), FALSE));
2238         if (win != NULL) {
2239                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2240                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2241                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2242         }
2243
2244         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2245
2246         /* If there was any error do nothing */
2247         if (modest_mail_operation_get_error (mail_op) != NULL)
2248                 return;
2249
2250         modest_msg_edit_window_set_draft (edit_window, saved_draft);
2251 }
2252
2253 void
2254 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2255 {
2256         TnyTransportAccount *transport_account;
2257         ModestMailOperation *mail_operation;
2258         MsgData *data;
2259         gchar *account_name, *from;
2260         ModestAccountMgr *account_mgr;
2261         char *info_text;
2262
2263         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2264         
2265         data = modest_msg_edit_window_get_msg_data (edit_window);
2266
2267         account_name = g_strdup (data->account_name);
2268         account_mgr = modest_runtime_get_account_mgr();
2269         if (!account_name)
2270                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2271         if (!account_name) 
2272                 account_name = modest_account_mgr_get_default_account (account_mgr);
2273         if (!account_name) {
2274                 g_printerr ("modest: no account found\n");
2275                 modest_msg_edit_window_free_msg_data (edit_window, data);
2276                 return;
2277         }
2278
2279         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2280                 account_name = g_strdup (data->account_name);
2281         }
2282
2283         transport_account =
2284                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2285                                       (modest_runtime_get_account_store(),
2286                                        account_name,
2287                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2288         if (!transport_account) {
2289                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2290                 g_free (account_name);
2291                 modest_msg_edit_window_free_msg_data (edit_window, data);
2292                 return;
2293         }
2294         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2295
2296         /* Create the mail operation */         
2297         mail_operation = modest_mail_operation_new (G_OBJECT(edit_window));
2298         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2299
2300         modest_mail_operation_save_to_drafts (mail_operation,
2301                                               transport_account,
2302                                               data->draft_msg,
2303                                               from,
2304                                               data->to, 
2305                                               data->cc, 
2306                                               data->bcc,
2307                                               data->subject, 
2308                                               data->plain_body, 
2309                                               data->html_body,
2310                                               data->attachments,
2311                                               data->images,
2312                                               data->priority_flags,
2313                                               on_save_to_drafts_cb,
2314                                               edit_window);
2315         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2316         modest_platform_information_banner (NULL, NULL, info_text);
2317
2318         /* Frees */
2319         g_free (info_text);
2320         g_free (from);
2321         g_free (account_name);
2322         g_object_unref (G_OBJECT (transport_account));
2323         g_object_unref (G_OBJECT (mail_operation));
2324
2325         modest_msg_edit_window_free_msg_data (edit_window, data);
2326         modest_msg_edit_window_reset_modified (edit_window);
2327
2328         /* ** FIXME **
2329          * If the drafts folder is selected then make the header view
2330          * insensitive while the message is being saved to drafts
2331          * (it'll be sensitive again in on_save_to_drafts_cb()). This
2332          * is not very clean but it avoids letting the drafts folder
2333          * in an inconsistent state: the user could edit the message
2334          * being saved and undesirable things would happen.
2335          * In the average case the user won't notice anything at
2336          * all. In the worst case (the user is editing a really big
2337          * file from Drafts) the header view will be insensitive
2338          * during the saving process (10 or 20 seconds, depending on
2339          * the message). Anyway this is just a quick workaround: once
2340          * we find a better solution it should be removed
2341          * See NB#65125 (commend #18) for details.
2342          */
2343         ModestMainWindow *win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2344                 modest_runtime_get_window_mgr(), FALSE));
2345         if (win != NULL) {
2346                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2347                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2348                 if (view != NULL) {
2349                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2350                         if (folder) {
2351                                 if (modest_tny_folder_is_local_folder(folder)) {
2352                                         TnyFolderType folder_type;
2353                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2354                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2355                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2356                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2357                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2358                                         }
2359                                 }
2360                         }
2361                         if (folder != NULL) g_object_unref(folder);
2362                 }
2363         }
2364 }
2365
2366 /* For instance, when clicking the Send toolbar button when editing a message: */
2367 void
2368 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2369 {
2370         TnyTransportAccount *transport_account = NULL;
2371
2372         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2373
2374         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2375                 return;
2376         
2377         /* FIXME: Code added just for testing. The final version will
2378            use the send queue provided by tinymail and some
2379            classifier */
2380         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2381
2382         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2383         gchar *account_name = g_strdup (data->account_name);
2384         if (!account_name)
2385                 g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2386
2387         if (!account_name) 
2388                 account_name = modest_account_mgr_get_default_account (account_mgr);
2389                 
2390         if (!account_name) {
2391                 modest_msg_edit_window_free_msg_data (edit_window, data);
2392                 /* Run account setup wizard */
2393                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window)))
2394                         return;
2395         }
2396         
2397         /* Get the currently-active transport account for this modest account: */
2398         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2399                 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2400                                                           (modest_runtime_get_account_store(),
2401                                                            account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2402         }
2403         
2404         if (!transport_account) {
2405                 /* Run account setup wizard */
2406                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2407                         return;
2408         }
2409         
2410         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2411
2412         /* Create the mail operation */
2413         ModestMailOperation *mail_operation = modest_mail_operation_new (G_OBJECT(edit_window));
2414         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2415
2416         modest_mail_operation_send_new_mail (mail_operation,
2417                                              transport_account,
2418                                              data->draft_msg,
2419                                              from,
2420                                              data->to, 
2421                                              data->cc, 
2422                                              data->bcc,
2423                                              data->subject, 
2424                                              data->plain_body, 
2425                                              data->html_body,
2426                                              data->attachments,
2427                                              data->images,
2428                                              data->priority_flags);
2429
2430         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2431                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2432
2433                                              
2434         /* Free data: */
2435         g_free (from);
2436         g_free (account_name);
2437         g_object_unref (G_OBJECT (transport_account));
2438         g_object_unref (G_OBJECT (mail_operation));
2439
2440         modest_msg_edit_window_free_msg_data (edit_window, data);
2441         modest_msg_edit_window_set_sent (edit_window, TRUE);
2442
2443         /* Save settings and close the window: */
2444         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2445 }
2446
2447 void 
2448 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2449                                   ModestMsgEditWindow *window)
2450 {
2451         ModestMsgEditFormatState *format_state = NULL;
2452
2453         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2454         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2455
2456         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2457                 return;
2458
2459         format_state = modest_msg_edit_window_get_format_state (window);
2460         g_return_if_fail (format_state != NULL);
2461
2462         format_state->bold = gtk_toggle_action_get_active (action);
2463         modest_msg_edit_window_set_format_state (window, format_state);
2464         g_free (format_state);
2465         
2466 }
2467
2468 void 
2469 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2470                                      ModestMsgEditWindow *window)
2471 {
2472         ModestMsgEditFormatState *format_state = NULL;
2473
2474         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2475         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2476
2477         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2478                 return;
2479
2480         format_state = modest_msg_edit_window_get_format_state (window);
2481         g_return_if_fail (format_state != NULL);
2482
2483         format_state->italics = gtk_toggle_action_get_active (action);
2484         modest_msg_edit_window_set_format_state (window, format_state);
2485         g_free (format_state);
2486         
2487 }
2488
2489 void 
2490 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2491                                      ModestMsgEditWindow *window)
2492 {
2493         ModestMsgEditFormatState *format_state = NULL;
2494
2495         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2496         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2497
2498         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2499                 return;
2500
2501         format_state = modest_msg_edit_window_get_format_state (window);
2502         g_return_if_fail (format_state != NULL);
2503
2504         format_state->bullet = gtk_toggle_action_get_active (action);
2505         modest_msg_edit_window_set_format_state (window, format_state);
2506         g_free (format_state);
2507         
2508 }
2509
2510 void 
2511 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2512                                      GtkRadioAction *selected,
2513                                      ModestMsgEditWindow *window)
2514 {
2515         ModestMsgEditFormatState *format_state = NULL;
2516         GtkJustification value;
2517
2518         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2519
2520         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2521                 return;
2522
2523         value = gtk_radio_action_get_current_value (selected);
2524
2525         format_state = modest_msg_edit_window_get_format_state (window);
2526         g_return_if_fail (format_state != NULL);
2527
2528         format_state->justification = value;
2529         modest_msg_edit_window_set_format_state (window, format_state);
2530         g_free (format_state);
2531 }
2532
2533 void 
2534 modest_ui_actions_on_select_editor_color (GtkAction *action,
2535                                           ModestMsgEditWindow *window)
2536 {
2537         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2538         g_return_if_fail (GTK_IS_ACTION (action));
2539
2540         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2541                 return;
2542
2543         modest_msg_edit_window_select_color (window);
2544 }
2545
2546 void 
2547 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2548                                                      ModestMsgEditWindow *window)
2549 {
2550         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2551         g_return_if_fail (GTK_IS_ACTION (action));
2552
2553         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2554                 return;
2555
2556         modest_msg_edit_window_select_background_color (window);
2557 }
2558
2559 void 
2560 modest_ui_actions_on_insert_image (GtkAction *action,
2561                                    ModestMsgEditWindow *window)
2562 {
2563         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2564         g_return_if_fail (GTK_IS_ACTION (action));
2565
2566         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2567                 return;
2568
2569         modest_msg_edit_window_insert_image (window);
2570 }
2571
2572 void 
2573 modest_ui_actions_on_attach_file (GtkAction *action,
2574                                   ModestMsgEditWindow *window)
2575 {
2576         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2577         g_return_if_fail (GTK_IS_ACTION (action));
2578
2579         modest_msg_edit_window_offer_attach_file (window);
2580 }
2581
2582 void 
2583 modest_ui_actions_on_remove_attachments (GtkAction *action,
2584                                          ModestMsgEditWindow *window)
2585 {
2586         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2587         g_return_if_fail (GTK_IS_ACTION (action));
2588
2589         modest_msg_edit_window_remove_attachments (window, NULL);
2590 }
2591
2592 static void
2593 do_create_folder_cb (ModestMailOperation *mail_op,
2594                      TnyFolderStore *parent_folder, 
2595                      TnyFolder *new_folder,
2596                      gpointer user_data)
2597 {
2598         gchar *suggested_name = (gchar *) user_data;
2599         GtkWindow *main_window = (GtkWindow *) modest_mail_operation_get_source (mail_op);
2600
2601         if (modest_mail_operation_get_error (mail_op)) {
2602                 /* Show an error */
2603                 modest_platform_information_banner (GTK_WIDGET (main_window), NULL,
2604                                                     _("mail_in_ui_folder_create_error"));
2605
2606                 /* Try again */
2607                 do_create_folder (main_window, parent_folder, (const gchar *) suggested_name);
2608         } else {
2609                 GtkWidget *folder_view;
2610
2611                 folder_view = 
2612                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
2613                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2614
2615                 /* Select the newly created folder */
2616                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
2617                                                   new_folder, FALSE);
2618                 g_object_unref (new_folder);
2619         }
2620         /* Free. Note that the first time it'll be NULL so noop */
2621         g_free (suggested_name);
2622         g_object_unref (main_window);
2623 }
2624
2625 static void
2626 do_create_folder (GtkWindow *parent_window, 
2627                   TnyFolderStore *parent_folder, 
2628                   const gchar *suggested_name)
2629 {
2630         gint result;
2631         gchar *folder_name = NULL;
2632
2633         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2634                                                         parent_folder,
2635                                                         (gchar *) suggested_name,
2636                                                         &folder_name);
2637         
2638         if (result == GTK_RESPONSE_ACCEPT) {
2639                 ModestMailOperation *mail_op;
2640                 
2641                 mail_op  = modest_mail_operation_new (G_OBJECT(parent_window));
2642                         
2643                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2644                                                  mail_op);
2645                 modest_mail_operation_create_folder (mail_op,
2646                                                      parent_folder,
2647                                                      (const gchar *) folder_name,
2648                                                      do_create_folder_cb,
2649                                                      folder_name);
2650                 g_object_unref (mail_op);
2651         }
2652 }
2653
2654
2655 static void
2656 modest_ui_actions_create_folder(GtkWidget *parent_window,
2657                                 GtkWidget *folder_view)
2658 {
2659         TnyFolderStore *parent_folder;
2660
2661         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2662         
2663         if (parent_folder) {
2664         
2665                 /* Run the new folder dialog */
2666                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
2667         
2668                 g_object_unref (parent_folder);
2669         }
2670 }
2671
2672 void 
2673 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2674 {
2675         GtkWidget *folder_view;
2676         
2677         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2678
2679         folder_view = modest_main_window_get_child_widget (main_window,
2680                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2681         if (!folder_view)
2682                 return;
2683
2684         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2685 }
2686
2687 static void
2688 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2689                                                gpointer user_data)
2690 {
2691         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2692         const GError *error = NULL;
2693         const gchar *message = NULL;
2694         
2695         /* Get error message */
2696         error = modest_mail_operation_get_error (mail_op);
2697         if (!error)
2698                 g_return_if_reached ();
2699
2700         switch (error->code) {
2701         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2702                 message = _CS("ckdg_ib_folder_already_exists");
2703                 break;
2704         default:
2705                 g_warning ("%s: BUG: unexpected error:[%d]: %s", __FUNCTION__,
2706                            error->code, error->message);
2707                 return;
2708         }
2709
2710         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2711 }
2712
2713 typedef struct {
2714         TnyFolderStore *folder;
2715         gchar *new_name;
2716 } RenameFolderInfo;
2717
2718 static void
2719 on_rename_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
2720                 TnyAccount *account, gpointer user_data)
2721 {
2722         ModestMailOperation *mail_op = NULL;
2723         GtkTreeSelection *sel = NULL;
2724         GtkWidget *folder_view = NULL;
2725         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
2726
2727         if (!canceled && (err == NULL) && MODEST_IS_MAIN_WINDOW(parent_window)) {
2728
2729                 folder_view = modest_main_window_get_child_widget (
2730                                 MODEST_MAIN_WINDOW (parent_window),
2731                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2732
2733                 mail_op = 
2734                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2735                                         modest_ui_actions_rename_folder_error_handler,
2736                                         parent_window, NULL);
2737
2738                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2739                                 mail_op);
2740
2741                 /* Clear the headers view */
2742                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2743                 gtk_tree_selection_unselect_all (sel);
2744
2745                 /* Select *after* the changes */
2746                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2747                                 TNY_FOLDER(data->folder), TRUE);
2748
2749                 /* Actually rename the folder */
2750                 modest_mail_operation_rename_folder (mail_op,
2751                                 TNY_FOLDER (data->folder),
2752                                 (const gchar *) (data->new_name));
2753                 
2754                 /* TODO folder view filter refilter */
2755                 /* 
2756                 GtkTreeModel *tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view));
2757                 if (GTK_IS_TREE_MODEL_FILTER (tree_model))
2758                         gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (tree_model)); */
2759         }
2760
2761         g_object_unref (mail_op);
2762         g_free (data->new_name);
2763         g_free (data);
2764 }
2765
2766 void 
2767 modest_ui_actions_on_rename_folder (GtkAction *action,
2768                                      ModestMainWindow *main_window)
2769 {
2770         TnyFolderStore *folder;
2771         GtkWidget *folder_view;
2772         GtkWidget *header_view; 
2773
2774         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2775
2776         folder_view = modest_main_window_get_child_widget (main_window,
2777                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2778         if (!folder_view)
2779                 return;
2780
2781         header_view = modest_main_window_get_child_widget (main_window,
2782                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2783         
2784         if (!header_view)
2785                 return;
2786
2787         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2788
2789         if (!folder)
2790                 return;
2791
2792         if (TNY_IS_FOLDER (folder)) {
2793                 gchar *folder_name;
2794                 gint response;
2795                 const gchar *current_name;
2796                 TnyFolderStore *parent;
2797                 gboolean do_rename = TRUE;
2798
2799                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2800                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2801                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2802                                                                      parent, current_name, 
2803                                                                      &folder_name);
2804                 g_object_unref (parent);
2805
2806                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2807                         do_rename = FALSE;
2808                 } else {
2809                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
2810                         rename_folder_data->folder = folder;
2811                         rename_folder_data->new_name = folder_name;
2812                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), 
2813                                         folder, on_rename_folder_cb, rename_folder_data);
2814                 }
2815         }
2816         g_object_unref (folder);
2817 }
2818
2819 static void
2820 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2821                                                gpointer user_data)
2822 {
2823         GObject *win = modest_mail_operation_get_source (mail_op);
2824
2825         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2826                                                 _("mail_in_ui_folder_delete_error"));
2827         g_object_unref (win);
2828 }
2829
2830 typedef struct {
2831         TnyFolderStore *folder;
2832         gboolean move_to_trash;
2833 } DeleteFolderInfo;
2834
2835 static void
2836 on_delete_folder_cb (gboolean canceled, 
2837                   GError *err,
2838                   GtkWindow *parent_window, 
2839                   TnyAccount *account, 
2840                   gpointer user_data)
2841 {
2842         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
2843         GtkWidget *folder_view;
2844         ModestMailOperation *mail_op;
2845         GtkTreeSelection *sel;
2846         
2847         if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
2848                 g_object_unref (G_OBJECT (info->folder));
2849                 g_free (info);
2850         }
2851         
2852         folder_view = modest_main_window_get_child_widget (
2853                         MODEST_MAIN_WINDOW (parent_window),
2854                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2855
2856         /* Unselect the folder before deleting it to free the headers */
2857         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2858         gtk_tree_selection_unselect_all (sel);
2859
2860         /* Create the mail operation */
2861         mail_op =
2862                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2863                                 modest_ui_actions_delete_folder_error_handler,
2864                                 NULL, NULL);
2865
2866         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2867                         mail_op);
2868         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
2869         
2870         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2871
2872         g_object_unref (G_OBJECT (mail_op));
2873         g_object_unref (G_OBJECT (info->folder));
2874         g_free (info);
2875 }
2876
2877 static void
2878 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
2879 {
2880         TnyFolderStore *folder;
2881         GtkWidget *folder_view;
2882         gint response;
2883         gchar *message;
2884         
2885         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2886
2887         folder_view = modest_main_window_get_child_widget (main_window,
2888                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2889         if (!folder_view)
2890                 return;
2891
2892         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2893
2894         /* Show an error if it's an account */
2895         if (!TNY_IS_FOLDER (folder)) {
2896                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2897                                                         _("mail_in_ui_folder_delete_error"));
2898                 g_object_unref (G_OBJECT (folder));
2899                 return;
2900         }
2901
2902         /* Ask the user */      
2903         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2904                                     tny_folder_get_name (TNY_FOLDER (folder)));
2905         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2906                                                             (const gchar *) message);
2907         g_free (message);
2908
2909         if (response == GTK_RESPONSE_OK) {
2910                 DeleteFolderInfo *info;
2911                 info = g_new0(DeleteFolderInfo, 1);
2912                 info->folder = folder;
2913                 info->move_to_trash = move_to_trash;
2914                 g_object_ref (G_OBJECT (info->folder));
2915                 TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2916                 modest_platform_connect_and_perform (GTK_WINDOW (main_window), 
2917                                 account, on_delete_folder_cb, info);
2918                 g_object_unref (account);
2919         }
2920         g_object_unref (G_OBJECT (folder));
2921 }
2922
2923 void 
2924 modest_ui_actions_on_delete_folder (GtkAction *action,
2925                                      ModestMainWindow *main_window)
2926 {
2927         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2928         
2929         delete_folder (main_window, FALSE);
2930 }
2931
2932 void 
2933 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2934 {
2935         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2936         
2937         delete_folder (main_window, TRUE);
2938 }
2939
2940
2941 static void
2942 show_error (GtkWidget *parent_widget, const gchar* text)
2943 {
2944         modest_platform_information_banner(parent_widget, NULL, text);
2945         
2946 #if 0
2947         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2948         /*
2949           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2950           (GtkDialogFlags)0,
2951           GTK_MESSAGE_ERROR,
2952           GTK_BUTTONS_OK,
2953           text ));
2954         */
2955                  
2956         gtk_dialog_run (dialog);
2957         gtk_widget_destroy (GTK_WIDGET (dialog));
2958 #endif
2959 }
2960
2961 void
2962 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2963                                          const gchar* server_account_name,
2964                                          gchar **username,
2965                                          gchar **password, 
2966                                          gboolean *cancel, 
2967                                          gboolean *remember,
2968                                          ModestMainWindow *main_window)
2969 {
2970         g_return_if_fail(server_account_name);
2971         
2972         /* Initalize output parameters: */
2973         if (cancel)
2974                 *cancel = FALSE;
2975                 
2976         if (remember)
2977                 *remember = TRUE;
2978                 
2979 #ifdef MODEST_PLATFORM_MAEMO
2980         /* Maemo uses a different (awkward) button order,
2981          * It should probably just use gtk_alternative_dialog_button_order ().
2982          */
2983         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2984                                               NULL,
2985                                               GTK_DIALOG_MODAL,
2986                                               _("mcen_bd_dialog_ok"),
2987                                               GTK_RESPONSE_ACCEPT,
2988                                               _("mcen_bd_dialog_cancel"),
2989                                               GTK_RESPONSE_REJECT,
2990                                               NULL);
2991 #else
2992         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2993                                               NULL,
2994                                               GTK_DIALOG_MODAL,
2995                                               GTK_STOCK_CANCEL,
2996                                               GTK_RESPONSE_REJECT,
2997                                               GTK_STOCK_OK,
2998                                               GTK_RESPONSE_ACCEPT,
2999                                               NULL);
3000 #endif /* MODEST_PLATFORM_MAEMO */
3001
3002         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3003         
3004         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3005                 modest_runtime_get_account_mgr(), server_account_name);
3006         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3007                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3008                 if (cancel)
3009                         *cancel = TRUE;
3010                 return;
3011         }
3012         
3013         /* This causes a warning because the logical ID has no %s in it, 
3014          * though the translation does, but there is not much we can do about that: */
3015         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3016         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3017                             FALSE, FALSE, 0);
3018         g_free (txt);
3019         g_free (server_name);
3020         server_name = NULL;
3021
3022         /* username: */
3023         gchar *initial_username = modest_account_mgr_get_server_account_username (
3024                 modest_runtime_get_account_mgr(), server_account_name);
3025         
3026         GtkWidget *entry_username = gtk_entry_new ();
3027         if (initial_username)
3028                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3029         /* Dim this if a connection has ever succeeded with this username,
3030          * as per the UI spec: */
3031         const gboolean username_known = 
3032                 modest_account_mgr_get_server_account_username_has_succeeded(
3033                         modest_runtime_get_account_mgr(), server_account_name);
3034         gtk_widget_set_sensitive (entry_username, !username_known);
3035         
3036 #ifdef MODEST_PLATFORM_MAEMO
3037         /* Auto-capitalization is the default, so let's turn it off: */
3038         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3039         
3040         /* Create a size group to be used by all captions.
3041          * Note that HildonCaption does not create a default size group if we do not specify one.
3042          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3043         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3044         
3045         GtkWidget *caption = hildon_caption_new (sizegroup, 
3046                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3047         gtk_widget_show (entry_username);
3048         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3049                 FALSE, FALSE, MODEST_MARGIN_HALF);
3050         gtk_widget_show (caption);
3051 #else 
3052         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3053                             TRUE, FALSE, 0);
3054 #endif /* MODEST_PLATFORM_MAEMO */      
3055                             
3056         /* password: */
3057         GtkWidget *entry_password = gtk_entry_new ();
3058         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3059         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3060         
3061 #ifdef MODEST_PLATFORM_MAEMO
3062         /* Auto-capitalization is the default, so let's turn it off: */
3063         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
3064                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3065         
3066         caption = hildon_caption_new (sizegroup, 
3067                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3068         gtk_widget_show (entry_password);
3069         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3070                 FALSE, FALSE, MODEST_MARGIN_HALF);
3071         gtk_widget_show (caption);
3072         g_object_unref (sizegroup);
3073 #else 
3074         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3075                             TRUE, FALSE, 0);
3076 #endif /* MODEST_PLATFORM_MAEMO */      
3077
3078         if (initial_username != NULL)
3079                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3080                                 
3081 /* This is not in the Maemo UI spec:
3082         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3083         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3084                             TRUE, FALSE, 0);
3085 */
3086
3087         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3088         
3089         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3090                 if (username) {
3091                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3092                         
3093                         modest_account_mgr_set_server_account_username (
3094                                  modest_runtime_get_account_mgr(), server_account_name, 
3095                                  *username);
3096                                  
3097                         const gboolean username_was_changed = 
3098                                 (strcmp (*username, initial_username) != 0);
3099                         if (username_was_changed) {
3100                                 g_warning ("%s: tinymail does not yet support changing the "
3101                                         "username in the get_password() callback.\n", __FUNCTION__);
3102                         }
3103                 }
3104                         
3105                 if (password) {
3106                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3107                         
3108                         /* We do not save the password in the configuration, 
3109                          * because this function is only called for passwords that should 
3110                          * not be remembered:
3111                         modest_server_account_set_password (
3112                                  modest_runtime_get_account_mgr(), server_account_name, 
3113                                  *password);
3114                         */
3115                 }
3116                 
3117                 if (cancel)
3118                         *cancel   = FALSE;
3119                         
3120         } else {
3121                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
3122                 
3123                 if (username)
3124                         *username = NULL;
3125                         
3126                 if (password)
3127                         *password = NULL;
3128                         
3129                 if (cancel)
3130                         *cancel   = TRUE;
3131         }
3132
3133 /* This is not in the Maemo UI spec:
3134         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3135                 *remember = TRUE;
3136         else
3137                 *remember = FALSE;
3138 */
3139
3140         gtk_widget_destroy (dialog);
3141         
3142         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3143 }
3144
3145 void
3146 modest_ui_actions_on_cut (GtkAction *action,
3147                           ModestWindow *window)
3148 {
3149         GtkWidget *focused_widget;
3150         GtkClipboard *clipboard;
3151
3152         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3153         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3154         if (GTK_IS_EDITABLE (focused_widget)) {
3155                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3156                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3157                 gtk_clipboard_store (clipboard);
3158         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3159                 GtkTextBuffer *buffer;
3160
3161                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3162                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3163                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3164                 gtk_clipboard_store (clipboard);
3165         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3166                 TnyList *header_list = modest_header_view_get_selected_headers (
3167                                 MODEST_HEADER_VIEW (focused_widget));
3168                 gboolean continue_download = FALSE;
3169                 gint num_of_unc_msgs;
3170
3171                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3172
3173                 if (num_of_unc_msgs) {
3174                         TnyAccount *account = get_account_from_header_list (header_list);
3175                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3176                         g_object_unref (account);
3177                 }
3178
3179                 if (num_of_unc_msgs == 0 || continue_download) {
3180 /*                      modest_platform_information_banner (
3181                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3182                         modest_header_view_cut_selection (
3183                                         MODEST_HEADER_VIEW (focused_widget));
3184                 }
3185
3186                 g_object_unref (header_list);
3187         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3188                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3189         }
3190 }
3191
3192 void
3193 modest_ui_actions_on_copy (GtkAction *action,
3194                            ModestWindow *window)
3195 {
3196         GtkClipboard *clipboard;
3197         GtkWidget *focused_widget;
3198         gboolean copied = TRUE;
3199
3200         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3201         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3202
3203         if (GTK_IS_LABEL (focused_widget)) {
3204                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
3205                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3206                 gtk_clipboard_store (clipboard);
3207         } else if (GTK_IS_EDITABLE (focused_widget)) {
3208                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3209                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3210                 gtk_clipboard_store (clipboard);
3211         } else if (GTK_IS_HTML (focused_widget)) {
3212                 gtk_html_copy (GTK_HTML (focused_widget));
3213                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3214                 gtk_clipboard_store (clipboard);
3215         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3216                 GtkTextBuffer *buffer;
3217                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3218                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3219                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3220                 gtk_clipboard_store (clipboard);
3221         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3222                 TnyList *header_list = modest_header_view_get_selected_headers (
3223                                 MODEST_HEADER_VIEW (focused_widget));
3224                 gboolean continue_download = FALSE;
3225                 gint num_of_unc_msgs;
3226
3227                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3228
3229                 if (num_of_unc_msgs) {
3230                         TnyAccount *account = get_account_from_header_list (header_list);
3231                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3232                         g_object_unref (account);
3233                 }
3234
3235                 if (num_of_unc_msgs == 0 || continue_download) {
3236                         modest_platform_information_banner (
3237                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3238                         modest_header_view_copy_selection (
3239                                         MODEST_HEADER_VIEW (focused_widget));
3240                 } else
3241                         copied = FALSE;
3242
3243                 g_object_unref (header_list);
3244
3245         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3246                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3247         }
3248
3249         /* Show information banner if there was a copy to clipboard */
3250         if(copied)
3251                 modest_platform_information_banner (
3252                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3253 }
3254
3255 void
3256 modest_ui_actions_on_undo (GtkAction *action,
3257                            ModestWindow *window)
3258 {
3259         ModestEmailClipboard *clipboard = NULL;
3260
3261         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3262                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3263         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3264                 /* Clear clipboard source */
3265                 clipboard = modest_runtime_get_email_clipboard ();
3266                 modest_email_clipboard_clear (clipboard);               
3267         }
3268         else {
3269                 g_return_if_reached ();
3270         }
3271 }
3272
3273 void
3274 modest_ui_actions_on_redo (GtkAction *action,
3275                            ModestWindow *window)
3276 {
3277         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3278                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3279         }
3280         else {
3281                 g_return_if_reached ();
3282         }
3283 }
3284
3285
3286 static void
3287 destroy_information_note (ModestMailOperation *mail_op, gpointer user_data)
3288 {
3289         /* destroy information note */
3290         gtk_widget_destroy (GTK_WIDGET(user_data));
3291 }
3292
3293
3294 static void
3295 paste_as_attachment_free (gpointer data)
3296 {
3297         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3298
3299         gtk_widget_destroy (helper->banner);
3300         g_object_unref (helper->banner);
3301         g_free (helper);
3302 }
3303
3304 static void
3305 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3306                             TnyHeader *header,
3307                             TnyMsg *msg,
3308                             gpointer userdata)
3309 {
3310         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3311         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3312
3313         if (msg == NULL)
3314                 return;
3315
3316         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3317         
3318 }
3319
3320 void
3321 modest_ui_actions_on_paste (GtkAction *action,
3322                             ModestWindow *window)
3323 {
3324         GtkWidget *focused_widget = NULL;
3325         GtkWidget *inf_note = NULL;
3326         ModestMailOperation *mail_op = NULL;
3327
3328         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3329         if (GTK_IS_EDITABLE (focused_widget)) {
3330                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3331         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3332                 ModestEmailClipboard *e_clipboard = NULL;
3333                 e_clipboard = modest_runtime_get_email_clipboard ();
3334                 if (modest_email_clipboard_cleared (e_clipboard)) {
3335                         GtkTextBuffer *buffer;
3336                         GtkClipboard *clipboard;
3337
3338                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3339                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3340                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3341                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3342                         ModestMailOperation *mail_op;
3343                         TnyFolder *src_folder;
3344                         TnyList *data;
3345                         gboolean delete;
3346                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3347                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3348                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3349                                                                            _CS("ckct_nw_pasting"));
3350                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3351                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3352                         if (helper->banner != NULL) {
3353                                 g_object_ref (G_OBJECT (helper->banner));
3354                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3355                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3356                         }
3357
3358                         if (data != NULL) {
3359                                 modest_mail_operation_get_msgs_full (mail_op, 
3360                                                                      data,
3361                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3362                                                                      helper,
3363                                                                      paste_as_attachment_free);
3364                         }
3365                 }
3366         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3367                 ModestEmailClipboard *clipboard = NULL;
3368                 TnyFolder *src_folder = NULL;
3369                 TnyFolderStore *folder_store = NULL;
3370                 TnyList *data = NULL;           
3371                 gboolean delete = FALSE;
3372                 
3373                 /* Check clipboard source */
3374                 clipboard = modest_runtime_get_email_clipboard ();
3375                 if (modest_email_clipboard_cleared (clipboard)) 
3376                         return;
3377                 
3378                 /* Get elements to paste */
3379                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3380
3381                 /* Create a new mail operation */
3382                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3383                 
3384                 /* Get destination folder */
3385                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3386
3387                 /* transfer messages  */
3388                 if (data != NULL) {
3389                         gint response = 0;
3390
3391                         /* Ask for user confirmation */
3392                         response = 
3393                                 modest_ui_actions_msgs_move_to_confirmation (window, 
3394                                                                              TNY_FOLDER (folder_store), 
3395                                                                              delete,
3396                                                                              data);
3397                         
3398                         if (response == GTK_RESPONSE_OK) {
3399                                 /* Launch notification */
3400                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3401                                                                              _CS("ckct_nw_pasting"));
3402                                 if (inf_note != NULL)  {
3403                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3404                                         gtk_widget_show (GTK_WIDGET(inf_note));
3405                                 }
3406
3407                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3408                                 modest_mail_operation_xfer_msgs (mail_op, 
3409                                                                  data,
3410                                                                  TNY_FOLDER (folder_store),
3411                                                                  delete,
3412                                                                  destroy_information_note,
3413                                                                  inf_note);                             
3414                         } else {
3415                                 g_object_unref (mail_op);
3416                         }
3417                         
3418                 } else if (src_folder != NULL) {                        
3419                         /* Launch notification */
3420                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3421                                                                      _CS("ckct_nw_pasting"));
3422                         if (inf_note != NULL)  {
3423                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3424                                 gtk_widget_show (GTK_WIDGET(inf_note));
3425                         }
3426                         
3427                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3428                         modest_mail_operation_xfer_folder (mail_op, 
3429                                                            src_folder,
3430                                                            folder_store,
3431                                                            delete,
3432                                                            destroy_information_note,
3433                                                            inf_note);
3434                 }
3435
3436                 /* Free */
3437                 if (data != NULL) 
3438                         g_object_unref (data);
3439                 if (src_folder != NULL) 
3440                         g_object_unref (src_folder);
3441                 if (folder_store != NULL) 
3442                         g_object_unref (folder_store);
3443         }
3444 }
3445
3446
3447 void
3448 modest_ui_actions_on_select_all (GtkAction *action,
3449                                  ModestWindow *window)
3450 {
3451         GtkWidget *focused_widget;
3452
3453         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3454         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3455                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3456         } else if (GTK_IS_LABEL (focused_widget)) {
3457                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3458         } else if (GTK_IS_EDITABLE (focused_widget)) {
3459                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3460         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3461                 GtkTextBuffer *buffer;
3462                 GtkTextIter start, end;
3463
3464                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3465                 gtk_text_buffer_get_start_iter (buffer, &start);
3466                 gtk_text_buffer_get_end_iter (buffer, &end);
3467                 gtk_text_buffer_select_range (buffer, &start, &end);
3468         } else if (GTK_IS_HTML (focused_widget)) {
3469                 gtk_html_select_all (GTK_HTML (focused_widget));
3470         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3471                 GtkWidget *header_view = focused_widget;
3472                 GtkTreeSelection *selection = NULL;
3473                 
3474                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3475                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3476                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3477                 }
3478                                 
3479                 /* Disable window dimming management */
3480                 modest_window_disable_dimming (MODEST_WINDOW(window));
3481                 
3482                 /* Select all messages */
3483                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3484                 gtk_tree_selection_select_all (selection);
3485
3486                 /* Set focuse on header view */
3487                 gtk_widget_grab_focus (header_view);
3488
3489
3490                 /* Enable window dimming management */
3491                 modest_window_enable_dimming (MODEST_WINDOW(window));
3492                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3493         }
3494
3495 }
3496
3497 void
3498 modest_ui_actions_on_mark_as_read (GtkAction *action,
3499                                    ModestWindow *window)
3500 {       
3501         g_return_if_fail (MODEST_IS_WINDOW(window));
3502                 
3503         /* Mark each header as read */
3504         do_headers_action (window, headers_action_mark_as_read, NULL);
3505 }
3506
3507 void
3508 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3509                                      ModestWindow *window)
3510 {       
3511         g_return_if_fail (MODEST_IS_WINDOW(window));
3512                 
3513         /* Mark each header as read */
3514         do_headers_action (window, headers_action_mark_as_unread, NULL);
3515 }
3516
3517 void
3518 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3519                                   GtkRadioAction *selected,
3520                                   ModestWindow *window)
3521 {
3522         gint value;
3523
3524         value = gtk_radio_action_get_current_value (selected);
3525         if (MODEST_IS_WINDOW (window)) {
3526                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3527         }
3528 }
3529
3530 void
3531 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3532                                                GtkRadioAction *selected,
3533                                                ModestWindow *window)
3534 {
3535         TnyHeaderFlags flags;
3536         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3537
3538         flags = gtk_radio_action_get_current_value (selected);
3539         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3540 }
3541
3542 void
3543 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3544                                                   GtkRadioAction *selected,
3545                                                   ModestWindow *window)
3546 {
3547         gint file_format;
3548
3549         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3550
3551         file_format = gtk_radio_action_get_current_value (selected);
3552         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3553 }
3554
3555
3556 void
3557 modest_ui_actions_on_zoom_plus (GtkAction *action,
3558                                 ModestWindow *window)
3559 {
3560         g_return_if_fail (MODEST_IS_WINDOW (window));
3561
3562         modest_window_zoom_plus (MODEST_WINDOW (window));
3563 }
3564
3565 void     
3566 modest_ui_actions_on_zoom_minus (GtkAction *action,
3567                                  ModestWindow *window)
3568 {
3569         g_return_if_fail (MODEST_IS_WINDOW (window));
3570
3571         modest_window_zoom_minus (MODEST_WINDOW (window));
3572 }
3573
3574 void     
3575 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3576                                            ModestWindow *window)
3577 {
3578         ModestWindowMgr *mgr;
3579         gboolean fullscreen, active;
3580         g_return_if_fail (MODEST_IS_WINDOW (window));
3581
3582         mgr = modest_runtime_get_window_mgr ();
3583
3584         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3585         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3586
3587         if (active != fullscreen) {
3588                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3589                 gtk_window_present (GTK_WINDOW (window));
3590         }
3591 }
3592
3593 void
3594 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3595                                         ModestWindow *window)
3596 {
3597         ModestWindowMgr *mgr;
3598         gboolean fullscreen;
3599
3600         g_return_if_fail (MODEST_IS_WINDOW (window));
3601
3602         mgr = modest_runtime_get_window_mgr ();
3603         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3604         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3605
3606         gtk_window_present (GTK_WINDOW (window));
3607 }
3608
3609 /* 
3610  * Used by modest_ui_actions_on_details to call do_headers_action 
3611  */
3612 static void
3613 headers_action_show_details (TnyHeader *header, 
3614                              ModestWindow *window,
3615                              gpointer user_data)
3616
3617 {
3618         GtkWidget *dialog;
3619         
3620         /* Create dialog */
3621         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3622
3623         /* Run dialog */
3624         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3625         gtk_widget_show_all (dialog);
3626         gtk_dialog_run (GTK_DIALOG (dialog));
3627
3628         gtk_widget_destroy (dialog);
3629 }
3630
3631 /*
3632  * Show the folder details in a ModestDetailsDialog widget
3633  */
3634 static void
3635 show_folder_details (TnyFolder *folder, 
3636                      GtkWindow *window)
3637 {
3638         GtkWidget *dialog;
3639         
3640         /* Create dialog */
3641         dialog = modest_details_dialog_new_with_folder (window, folder);
3642
3643         /* Run dialog */
3644         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3645         gtk_widget_show_all (dialog);
3646         gtk_dialog_run (GTK_DIALOG (dialog));
3647
3648         gtk_widget_destroy (dialog);
3649 }
3650
3651 /*
3652  * Show the header details in a ModestDetailsDialog widget
3653  */
3654 void     
3655 modest_ui_actions_on_details (GtkAction *action, 
3656                               ModestWindow *win)
3657 {
3658         TnyList * headers_list;
3659         TnyIterator *iter;
3660         TnyHeader *header;              
3661
3662         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3663                 TnyMsg *msg;
3664
3665                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3666                 if (!msg)
3667                         return;
3668                 g_object_unref (msg);           
3669
3670                 headers_list = get_selected_headers (win);
3671                 if (!headers_list)
3672                         return;
3673
3674                 iter = tny_list_create_iterator (headers_list);
3675
3676                 header = TNY_HEADER (tny_iterator_get_current (iter));
3677                 if (header) {
3678                         headers_action_show_details (header, win, NULL);
3679                         g_object_unref (header);
3680                 }
3681
3682                 g_object_unref (iter);
3683                 g_object_unref (headers_list);
3684
3685         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3686                 GtkWidget *folder_view, *header_view;
3687
3688                 /* Check which widget has the focus */
3689                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3690                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3691                 if (gtk_widget_is_focus (folder_view)) {
3692                         TnyFolderStore *folder_store
3693                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3694                         if (!folder_store) {
3695                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3696                                 return; 
3697                         }
3698                         /* Show only when it's a folder */
3699                         /* This function should not be called for account items, 
3700                          * because we dim the menu item for them. */
3701                         if (TNY_IS_FOLDER (folder_store)) {
3702                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3703                         }
3704
3705                         g_object_unref (folder_store);
3706
3707                 } else {
3708                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3709                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3710                         /* Show details of each header */
3711                         do_headers_action (win, headers_action_show_details, header_view);
3712                 }
3713         }
3714 }
3715
3716 void     
3717 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3718                                      ModestMsgEditWindow *window)
3719 {
3720         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3721
3722         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3723 }
3724
3725 void     
3726 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3727                                       ModestMsgEditWindow *window)
3728 {
3729         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3730
3731         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3732 }
3733
3734 void
3735 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3736                                        ModestMainWindow *main_window)
3737 {
3738         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3739
3740         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3741                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3742         else
3743                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3744 }
3745
3746 void 
3747 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3748                                      ModestWindow *window)
3749 {
3750         gboolean active, fullscreen = FALSE;
3751         ModestWindowMgr *mgr;
3752
3753         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3754
3755         /* Check if we want to toggle the toolbar vuew in fullscreen
3756            or normal mode */
3757         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3758                      "ViewShowToolbarFullScreen")) {
3759                 fullscreen = TRUE;
3760         }
3761
3762         /* Toggle toolbar */
3763         mgr = modest_runtime_get_window_mgr ();
3764         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3765 }
3766
3767 void     
3768 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3769                                            ModestMsgEditWindow *window)
3770 {
3771         modest_msg_edit_window_select_font (window);
3772 }
3773
3774 void
3775 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3776                                                   const gchar *display_name,
3777                                                   GtkWindow *window)
3778 {
3779         /* This is usually used to change the title of the main window, which
3780          * is the one that holds the folder view. Note that this change can
3781          * happen even when the widget doesn't have the focus. */
3782         if (display_name)
3783                 gtk_window_set_title (window, display_name);
3784         else
3785                 gtk_window_set_title (window, " ");
3786 }
3787
3788 void
3789 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3790 {
3791         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3792         modest_msg_edit_window_select_contacts (window);
3793 }
3794
3795 void
3796 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3797 {
3798         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3799         modest_msg_edit_window_check_names (window, FALSE);
3800 }
3801
3802 static void
3803 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3804 {
3805         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3806                                          GTK_WIDGET (user_data));
3807 }
3808
3809 /*
3810  * This function is used to track changes in the selection of the
3811  * folder view that is inside the "move to" dialog to enable/disable
3812  * the OK button because we do not want the user to select a disallowed
3813  * destination for a folder.
3814  * The user also not desired to be able to use NEW button on items where
3815  * folder creation is not possibel.
3816  */
3817 static void
3818 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3819                                             TnyFolderStore *folder_store,
3820                                             gboolean selected,
3821                                             gpointer user_data)
3822 {
3823         GtkWidget *dialog = NULL;
3824         GtkWidget *ok_button = NULL, *new_button = NULL;
3825         GList *children = NULL;
3826         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3827         gboolean moving_folder = FALSE;
3828         gboolean is_local_account = TRUE;
3829         GtkWidget *folder_view = NULL;
3830         ModestTnyFolderRules rules;
3831
3832         if (!selected)
3833                 return;
3834
3835         /* Get the OK button */
3836         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3837         if (!dialog)
3838                 return;
3839
3840         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3841         ok_button = GTK_WIDGET (children->next->next->data);
3842         new_button = GTK_WIDGET (children->next->data);
3843         g_list_free (children);
3844
3845         /* check if folder_store is an remote account */
3846         if (TNY_IS_ACCOUNT (folder_store)) {
3847                 TnyAccount *local_account = NULL;
3848                 TnyAccount *mmc_account = NULL;
3849                 ModestTnyAccountStore *account_store = NULL;
3850
3851                 account_store = modest_runtime_get_account_store ();
3852                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3853                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
3854
3855                 if ((gpointer) local_account != (gpointer) folder_store &&
3856                     (gpointer) mmc_account != (gpointer) folder_store) {
3857                         is_local_account = FALSE;
3858                         /* New button should be dimmed on remote
3859                            account root */
3860                         new_sensitive = FALSE;
3861                 }
3862                 g_object_unref (local_account);
3863         }
3864
3865         /* Check the target folder rules */
3866         if (TNY_IS_FOLDER (folder_store)) {
3867                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3868                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3869                         ok_sensitive = FALSE;
3870                         new_sensitive = FALSE;
3871                         goto end;
3872                 }
3873         }
3874
3875         /* Check if we're moving a folder */
3876         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3877                 /* Get the widgets */
3878                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3879                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3880                 if (gtk_widget_is_focus (folder_view))
3881                         moving_folder = TRUE;
3882         }
3883
3884         if (moving_folder) {
3885                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3886
3887                 /* Get the folder to move */
3888                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3889                 
3890                 /* Check that we're not moving to the same folder */
3891                 if (TNY_IS_FOLDER (moved_folder)) {
3892                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3893                         if (parent == folder_store)
3894                                 ok_sensitive = FALSE;
3895                         g_object_unref (parent);
3896                 } 
3897
3898                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3899                         /* Do not allow to move to an account unless it's the
3900                            local folders account */
3901                         if (!is_local_account)
3902                                 ok_sensitive = FALSE;
3903                 } 
3904
3905                 if (ok_sensitive && (moved_folder == folder_store)) {
3906                         /* Do not allow to move to itself */
3907                         ok_sensitive = FALSE;
3908                 }
3909                 g_object_unref (moved_folder);
3910         } else {
3911                 TnyHeader *header = NULL;
3912                 TnyFolder *src_folder = NULL;
3913
3914                 /* Moving a message */
3915                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3916                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3917                         src_folder = tny_header_get_folder (header);
3918                         g_object_unref (header);
3919                 } else {
3920                         src_folder = 
3921                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3922                 }
3923
3924                 /* Do not allow to move the msg to the same folder */
3925                 /* Do not allow to move the msg to an account */
3926                 if ((gpointer) src_folder == (gpointer) folder_store ||
3927                     TNY_IS_ACCOUNT (folder_store))
3928                         ok_sensitive = FALSE;
3929                 g_object_unref (src_folder);
3930         }
3931
3932  end:
3933         /* Set sensitivity of the OK button */
3934         gtk_widget_set_sensitive (ok_button, ok_sensitive);
3935         /* Set sensitivity of the NEW button */
3936         gtk_widget_set_sensitive (new_button, new_sensitive);
3937 }
3938
3939 static GtkWidget*
3940 create_move_to_dialog (GtkWindow *win,
3941                        GtkWidget *folder_view,
3942                        GtkWidget **tree_view)
3943 {
3944         GtkWidget *dialog, *scroll;
3945         GtkWidget *new_button;
3946
3947         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3948                                               GTK_WINDOW (win),
3949                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3950                                               NULL);
3951
3952         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3953         /* We do this manually so GTK+ does not associate a response ID for
3954          * the button. */
3955         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3956         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3957         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3958
3959         /* Create scrolled window */
3960         scroll = gtk_scrolled_window_new (NULL, NULL);
3961         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3962                                          GTK_POLICY_AUTOMATIC,
3963                                          GTK_POLICY_AUTOMATIC);
3964
3965         /* Create folder view */
3966         *tree_view = modest_platform_create_folder_view (NULL);
3967
3968         /* Track changes in the selection to
3969          * disable the OK button whenever "Move to" is not possible
3970          * disbale NEW button whenever New is not possible */
3971         g_signal_connect (*tree_view,
3972                           "folder_selection_changed",
3973                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3974                           win);
3975
3976         /* Listen to clicks on New button */
3977         g_signal_connect (G_OBJECT (new_button), 
3978                           "clicked", 
3979                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3980                           *tree_view);
3981
3982         /* It could happen that we're trying to move a message from a
3983            window (msg window for example) after the main window was
3984            closed, so we can not just get the model of the folder
3985            view */
3986         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3987                 const gchar *visible_id = NULL;
3988
3989                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
3990                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
3991                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3992                                                MODEST_FOLDER_VIEW(*tree_view));
3993
3994                 visible_id = 
3995                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3996
3997                 /* Show the same account than the one that is shown in the main window */
3998                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3999                                                                              visible_id);
4000         } else {
4001                 const gchar *active_account_name = NULL;
4002                 ModestAccountMgr *mgr = NULL;
4003                 ModestAccountSettings *settings = NULL;
4004                 ModestServerAccountSettings *store_settings = NULL;
4005
4006                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4007                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4008                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4009                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4010
4011                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4012                 mgr = modest_runtime_get_account_mgr ();
4013                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4014
4015                 if (settings) {
4016                         const gchar *store_account_name;
4017                         store_settings = modest_account_settings_get_store_settings (settings);
4018                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4019
4020                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4021                                                                                      store_account_name);
4022                         g_object_unref (store_settings);
4023                         g_object_unref (settings);
4024                 }
4025         }
4026
4027         /* Hide special folders */
4028         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4029         
4030         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4031
4032         /* Add scroll to dialog */
4033         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4034                             scroll, TRUE, TRUE, 0);
4035
4036         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4037         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4038
4039         return dialog;
4040 }
4041
4042 /*
4043  * Returns TRUE if at least one of the headers of the list belongs to
4044  * a message that has been fully retrieved.
4045  */
4046 #if 0 /* no longer in use. delete in 2007.10 */
4047 static gboolean
4048 has_retrieved_msgs (TnyList *list)
4049 {
4050         TnyIterator *iter;
4051         gboolean found = FALSE;
4052
4053         iter = tny_list_create_iterator (list);
4054         while (!tny_iterator_is_done (iter) && !found) {
4055                 TnyHeader *header;
4056                 TnyHeaderFlags flags = 0;
4057
4058                 header = TNY_HEADER (tny_iterator_get_current (iter));
4059                 if (header) {
4060                         flags = tny_header_get_flags (header);
4061                         if (flags & TNY_HEADER_FLAG_CACHED)
4062 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
4063                                 found = TRUE;
4064
4065                         g_object_unref (header);
4066                 }
4067
4068                 if (!found)
4069                         tny_iterator_next (iter);
4070         }
4071         g_object_unref (iter);
4072
4073         return found;
4074 }
4075 #endif /* 0 */
4076
4077
4078 /*
4079  * Shows a confirmation dialog to the user when we're moving messages
4080  * from a remote server to the local storage. Returns the dialog
4081  * response. If it's other kind of movement then it always returns
4082  * GTK_RESPONSE_OK
4083  *
4084  * This one is used by the next functions:
4085  *      modest_ui_actions_on_paste                      - commented out
4086  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4087  */
4088 gint
4089 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4090                                              TnyFolder *dest_folder,
4091                                              gboolean delete,
4092                                              TnyList *headers)
4093 {
4094         gint response = GTK_RESPONSE_OK;
4095         TnyAccount *account = NULL;
4096         TnyFolder *src_folder = NULL;
4097         TnyIterator *iter = NULL;
4098         TnyHeader *header = NULL;
4099
4100         /* return with OK if the destination is a remote folder */
4101         if (modest_tny_folder_is_remote_folder (dest_folder))
4102                 return GTK_RESPONSE_OK;
4103
4104         /* Get source folder */
4105         iter = tny_list_create_iterator (headers);
4106         header = TNY_HEADER (tny_iterator_get_current (iter));
4107         if (header) {
4108                 src_folder = tny_header_get_folder (header);
4109                 g_object_unref (header);
4110         }
4111         g_object_unref (iter);
4112
4113         /* if no src_folder, message may be an attahcment */
4114         if (src_folder == NULL) 
4115                 return GTK_RESPONSE_CANCEL;
4116
4117         /* If the source is a local or MMC folder */
4118         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4119                 g_object_unref (src_folder);
4120                 return GTK_RESPONSE_OK;
4121         }
4122
4123         /* Get the account */
4124         account = tny_folder_get_account (src_folder);
4125
4126         /* now if offline we ask the user */
4127         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4128                 response = GTK_RESPONSE_OK;
4129         else
4130                 response = GTK_RESPONSE_CANCEL;
4131
4132         /* Frees */
4133         g_object_unref (src_folder);
4134         g_object_unref (account);
4135
4136         return response;
4137 }
4138
4139
4140
4141 static void
4142 move_to_cb (ModestMailOperation *mail_op, gpointer user_data)
4143 {
4144         MoveToHelper *helper = (MoveToHelper *) user_data;
4145
4146         /* Note that the operation could have failed, in that case do
4147            nothing */
4148         if (modest_mail_operation_get_status (mail_op) == 
4149             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4150
4151                 GObject *object = modest_mail_operation_get_source (mail_op);
4152                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4153                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4154
4155                         if (!modest_msg_view_window_select_next_message (self))
4156                                 if (!modest_msg_view_window_select_previous_message (self))
4157                                         /* No more messages to view, so close this window */
4158                                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4159                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4160                         GtkWidget *header_view;
4161                         GtkTreePath *path;
4162                         GtkTreeSelection *sel;
4163
4164                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4165                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4166                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4167                         path = gtk_tree_row_reference_get_path (helper->reference);
4168                         gtk_tree_selection_select_path (sel, path);
4169                         gtk_tree_path_free (path);
4170                 }
4171                 g_object_unref (object);
4172         }
4173
4174         /* Close the "Pasting" information banner */
4175         gtk_widget_destroy (GTK_WIDGET(helper->banner));
4176         if (helper->reference != NULL)
4177                 gtk_tree_row_reference_free (helper->reference);
4178         g_free (helper);
4179 }
4180
4181 void
4182 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4183                                              gpointer user_data)
4184 {
4185         ModestWindow *main_window = NULL;
4186         GObject *win = NULL;
4187         
4188         /* Disable next automatic folder selection */
4189         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4190                                                          FALSE); /* don't create */
4191         if (main_window) {
4192                 GtkWidget *folder_view = NULL;
4193         
4194                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4195                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4196                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4197                 
4198                 if (user_data && TNY_IS_FOLDER (user_data)) {
4199                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4200                                                           TNY_FOLDER (user_data), FALSE);
4201                 }
4202         }
4203
4204         /* Show notification dialog */
4205         win = modest_mail_operation_get_source (mail_op);
4206         modest_platform_run_information_dialog ((GtkWindow *) win, _("mail_in_ui_folder_move_target_error"));
4207         if (win)
4208                 g_object_unref (win);
4209 }
4210
4211 void
4212 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
4213                                               gpointer user_data)
4214 {
4215         GObject *win = modest_mail_operation_get_source (mail_op);
4216         const GError *error = modest_mail_operation_get_error (mail_op);
4217
4218         g_return_if_fail (error != NULL);
4219         if (error->message != NULL)             
4220                 g_printerr ("modest: %s\n", error->message);
4221         else
4222                 g_printerr ("modest: unkonw error on send&receive operation");
4223
4224         /* Show error message */
4225 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
4226 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4227 /*                                                      _CS("sfil_ib_unable_to_receive")); */
4228 /*      else  */
4229 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4230 /*                                                      _CS("sfil_ib_unable_to_send")); */
4231         g_object_unref (win);
4232 }
4233
4234 static void
4235 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4236                        TnyHeader *header, 
4237                        gboolean canceled,
4238                        TnyMsg *msg, 
4239                        GError *err,
4240                        gpointer user_data)
4241 {
4242         TnyList *parts;
4243         TnyIterator *iter;
4244         gint pending_purges = 0;
4245         gboolean some_purged = FALSE;
4246         ModestWindow *win = MODEST_WINDOW (user_data);
4247         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4248
4249         /* If there was any error */
4250         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4251                 modest_window_mgr_unregister_header (mgr, header);
4252                 return;
4253         }
4254
4255         /* Once the message has been retrieved for purging, we check if
4256          * it's all ok for purging */
4257
4258         parts = tny_simple_list_new ();
4259         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4260         iter = tny_list_create_iterator (parts);
4261
4262         while (!tny_iterator_is_done (iter)) {
4263                 TnyMimePart *part;
4264                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4265                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4266                         if (tny_mime_part_is_purged (part))
4267                                 some_purged = TRUE;
4268                         else
4269                                 pending_purges++;
4270                 }
4271
4272                 if (part)
4273                         g_object_unref (part);
4274
4275                 tny_iterator_next (iter);
4276         }
4277         g_object_unref (iter);
4278         
4279
4280         if (pending_purges>0) {
4281                 gint response;
4282                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4283
4284                 if (response == GTK_RESPONSE_OK) {
4285                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4286                         iter = tny_list_create_iterator (parts);
4287                         while (!tny_iterator_is_done (iter)) {
4288                                 TnyMimePart *part;
4289                                 
4290                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4291                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4292                                         tny_mime_part_set_purged (part);
4293
4294                                 if (part)
4295                                         g_object_unref (part);
4296
4297                                 tny_iterator_next (iter);
4298                         }
4299                         
4300                         tny_msg_rewrite_cache (msg);
4301                 }
4302      /* } else { */
4303                 /* This string no longer exists, refer to NB#75415 for more info */
4304                 /* modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged")); */
4305         }
4306         g_object_unref (iter);
4307
4308         modest_window_mgr_unregister_header (mgr, header);
4309
4310         g_object_unref (parts);
4311 }
4312
4313 static void
4314 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4315                                                      ModestMainWindow *win)
4316 {
4317         GtkWidget *header_view;
4318         TnyList *header_list;
4319         TnyIterator *iter;
4320         TnyHeader *header;
4321         TnyHeaderFlags flags;
4322         ModestWindow *msg_view_window =  NULL;
4323         gboolean found;
4324
4325         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4326
4327         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4328                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4329
4330         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4331         if (!header_list) {
4332                 g_warning ("%s: no header selected", __FUNCTION__);
4333                 return;
4334         }
4335         
4336         if (tny_list_get_length (header_list) == 1) {
4337                 iter = tny_list_create_iterator (header_list);
4338                 header = TNY_HEADER (tny_iterator_get_current (iter));
4339                 g_object_unref (iter);
4340         } else
4341                 return;
4342         
4343         if (!header || !TNY_IS_HEADER(header)) {
4344                 g_warning ("%s: header is not valid", __FUNCTION__);
4345                 return;
4346         }
4347         
4348         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4349                                                           header, &msg_view_window);
4350         flags = tny_header_get_flags (header);
4351         if (!(flags & TNY_HEADER_FLAG_CACHED))
4352                 return;
4353         if (found) {
4354                 if (msg_view_window != NULL) 
4355                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4356                 else {
4357                         /* do nothing; uid was registered before, so window is probably on it's way */
4358                         g_warning ("debug: header %p has already been registered", header);
4359                 }
4360         } else {
4361                 ModestMailOperation *mail_op = NULL;
4362                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4363                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4364                                                                          modest_ui_actions_get_msgs_full_error_handler,
4365                                                                          NULL, NULL);
4366                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4367                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4368                 
4369                 g_object_unref (mail_op);
4370         }
4371         if (header)
4372                 g_object_unref (header);
4373         if (header_list)
4374                 g_object_unref (header_list);
4375 }
4376
4377 /**
4378  * Utility function that transfer messages from both the main window
4379  * and the msg view window when using the "Move to" dialog
4380  */
4381 static void
4382 xfer_messages_from_move_to_cb  (gboolean canceled, GError *err,
4383                 GtkWindow *parent_window, 
4384                 TnyAccount *account, gpointer user_data)
4385 {
4386         TnyFolderStore *dst_folder = TNY_FOLDER_STORE (user_data);
4387         ModestWindow *win = MODEST_WINDOW (parent_window);
4388         TnyList *headers = NULL;
4389         TnyAccount *dst_account = NULL;
4390         const gchar *proto_str = NULL;
4391         gboolean dst_is_pop = FALSE;
4392
4393         if (canceled || err) {
4394                 g_object_unref (dst_folder);
4395                 return;
4396         }
4397         
4398         if (!TNY_IS_FOLDER (dst_folder)) {
4399                 modest_platform_information_banner (GTK_WIDGET (win),
4400                                                     NULL,
4401                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
4402                 return;
4403         }
4404
4405         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4406         proto_str = tny_account_get_proto (dst_account);
4407
4408         /* tinymail will return NULL for local folders it seems */
4409         dst_is_pop = proto_str &&
4410                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4411                  MODEST_PROTOCOL_STORE_POP);
4412
4413         g_object_unref (dst_account);
4414
4415         /* Get selected headers */
4416         headers = get_selected_headers (MODEST_WINDOW (win));
4417         if (!headers) {
4418                 g_warning ("%s: no headers selected", __FUNCTION__);
4419                 return;
4420         }
4421
4422
4423         if (dst_is_pop) {
4424                 modest_platform_information_banner (GTK_WIDGET (win),
4425                                                     NULL,
4426                                                     ngettext("mail_in_ui_folder_move_target_error",
4427                                                              "mail_in_ui_folder_move_targets_error",
4428                                                              tny_list_get_length (headers)));
4429                 g_object_unref (headers);
4430                 return;
4431         }
4432
4433         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4434         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4435                                                            _CS("ckct_nw_pasting"));
4436         if (helper->banner != NULL)  {
4437                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4438                 gtk_widget_show (GTK_WIDGET(helper->banner));
4439         }
4440
4441         if (MODEST_IS_MAIN_WINDOW (win)) {
4442                 GtkWidget *header_view = 
4443                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4444                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4445                 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4446         }
4447
4448         ModestMailOperation *mail_op = 
4449                 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4450                                                                modest_ui_actions_move_folder_error_handler,
4451                                                                NULL, NULL);
4452         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4453                                          mail_op);
4454
4455         modest_mail_operation_xfer_msgs (mail_op, 
4456                                          headers,
4457                                          TNY_FOLDER (dst_folder),
4458                                          TRUE,
4459                                          move_to_cb,
4460                                          helper);
4461
4462         g_object_unref (G_OBJECT (mail_op));
4463         g_object_unref (headers);
4464         g_object_unref (dst_folder);
4465 }
4466
4467 typedef struct {
4468         TnyFolder *src_folder;
4469         TnyFolderStore *dst_folder;
4470         gboolean delete_original;
4471         GtkWidget *folder_view;
4472 } MoveFolderInfo;
4473
4474 static void
4475 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
4476                 TnyAccount *account, gpointer user_data)
4477 {
4478         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
4479         GtkTreeSelection *sel;
4480         ModestMailOperation *mail_op = NULL;
4481         
4482         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
4483                 g_object_unref (G_OBJECT (info->src_folder));
4484                 g_object_unref (G_OBJECT (info->dst_folder));
4485                 g_free (info);
4486                 return;
4487         }
4488         
4489         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4490         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
4491                         _CS("ckct_nw_pasting"));
4492         if (helper->banner != NULL)  {
4493                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4494                 gtk_widget_show (GTK_WIDGET(helper->banner));
4495         }
4496         /* Clean folder on header view before moving it */
4497         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
4498         gtk_tree_selection_unselect_all (sel);
4499
4500         /* Let gtk events run. We need that the folder
4501            view frees its reference to the source
4502            folder *before* issuing the mail operation
4503            so we need the signal handler of selection
4504            changed to happen before the mail
4505            operation 
4506         while (gtk_events_pending ())
4507                 gtk_main_iteration ();   */
4508
4509         mail_op =
4510                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
4511                                 modest_ui_actions_move_folder_error_handler,
4512                                 info->src_folder, NULL);
4513         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4514                         mail_op);
4515
4516         /* Select *after* the changes */
4517         /* TODO: this function hangs UI after transfer */ 
4518         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4519         /*                                                        TNY_FOLDER (src_folder), TRUE); */
4520
4521         modest_mail_operation_xfer_folder (mail_op,
4522                         TNY_FOLDER (info->src_folder),
4523                         info->dst_folder,
4524                         info->delete_original, 
4525                         move_to_cb, 
4526                         helper);
4527         
4528         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
4529                         TNY_FOLDER (info->dst_folder), TRUE);
4530         
4531         /* Unref mail operation */
4532         g_object_unref (G_OBJECT (mail_op));
4533         g_object_unref (G_OBJECT (info->src_folder));
4534         g_object_unref (G_OBJECT (info->dst_folder));
4535         g_free (user_data);
4536 }
4537
4538 /*
4539  * UI handler for the "Move to" action when invoked from the
4540  * ModestMainWindow
4541  */
4542 static void 
4543 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4544                                           GtkWidget *folder_view,
4545                                           TnyFolderStore *dst_folder,
4546                                           ModestMainWindow *win)
4547 {
4548         ModestHeaderView *header_view = NULL;
4549         TnyFolderStore *src_folder;
4550         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4551
4552         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4553
4554         /* Get the source folder */
4555         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4556
4557         /* Get header view */
4558         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4559
4560         /* Get folder or messages to transfer */
4561         if (gtk_widget_is_focus (folder_view)) {
4562                 gboolean do_xfer = TRUE;
4563
4564                 /* Allow only to transfer folders to the local root folder */
4565                 if (TNY_IS_ACCOUNT (dst_folder) && 
4566                                 !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4567                                         do_xfer = FALSE;
4568                 } else if (!TNY_IS_FOLDER (src_folder)) {
4569                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4570                         do_xfer = FALSE;
4571                 } /* else if (!online && modest_tny_folder_store_is_remote(src_folder)) {
4572                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER (src_folder));
4573                         TnyAccount *account = tny_folder_get_account (TNY_FOLDER (src_folder));
4574                         if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4575                                 do_xfer = FALSE;
4576                         g_object_unref (account);
4577                 }*/
4578
4579                 if (do_xfer) {
4580                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
4581                         info->src_folder = TNY_FOLDER (src_folder);
4582                         info->dst_folder = dst_folder;
4583                         info->delete_original = TRUE;
4584                         info->folder_view = folder_view;
4585                         g_object_ref (G_OBJECT (info->src_folder));
4586                         g_object_ref (G_OBJECT (info->dst_folder));
4587                         modest_platform_connect_if_remote_and_perform(GTK_WINDOW (win), 
4588                                     TNY_FOLDER_STORE (dst_folder), on_move_folder_cb, info);
4589                 }
4590         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4591                 gboolean do_xfer = TRUE;
4592                 /* Ask for confirmation if the source folder is remote and we're not connected */
4593                 if (!online && modest_tny_folder_store_is_remote(src_folder)) {
4594                         TnyList *headers = modest_header_view_get_selected_headers(header_view);
4595                         if (!msgs_already_deleted_from_server(headers, src_folder)) {
4596                                 guint num_headers = tny_list_get_length(headers);
4597                                 TnyAccount *account = get_account_from_header_list (headers);
4598                                 if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4599                                         do_xfer = FALSE;
4600                                 g_object_unref (account);
4601                         }
4602                         g_object_unref(headers);
4603                 }
4604                 if (do_xfer) /* Transfer messages */ {
4605                         g_object_ref (dst_folder);
4606                         modest_platform_connect_if_remote_and_perform(GTK_WINDOW (win), 
4607                                         TNY_FOLDER_STORE (dst_folder), xfer_messages_from_move_to_cb, dst_folder);
4608                 }
4609         }
4610
4611         if (src_folder)
4612                 g_object_unref (src_folder);
4613 }
4614
4615
4616 /*
4617  * UI handler for the "Move to" action when invoked from the
4618  * ModestMsgViewWindow
4619  */
4620 static void 
4621 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4622                                               TnyFolderStore *dst_folder,
4623                                               ModestMsgViewWindow *win)
4624 {
4625         TnyHeader *header = NULL;
4626         TnyFolder *src_folder = NULL;
4627         TnyAccount *account = NULL;
4628         gboolean do_xfer = FALSE;
4629
4630         /* Create header list */
4631         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4632         src_folder = TNY_FOLDER (tny_header_get_folder(header));
4633         g_object_unref (header);
4634
4635         account = tny_folder_get_account (src_folder);
4636         if (!modest_tny_folder_store_is_remote(TNY_FOLDER_STORE(src_folder))) {
4637                 /* Transfer if the source folder is local */
4638                 do_xfer = TRUE;
4639         } else if (remote_folder_is_pop(TNY_FOLDER_STORE(src_folder))) {
4640                 /* Transfer if the source folder is POP (as it means
4641                  * that the message is already downloaded) */
4642                 do_xfer = TRUE;
4643         } else if (connect_to_get_msg(MODEST_WINDOW(win), 1, account)) {
4644                 /* Transfer after asking confirmation */
4645                 do_xfer = TRUE;
4646         }
4647
4648         if (do_xfer) {
4649                 g_object_ref (dst_folder);
4650                 modest_platform_connect_if_remote_and_perform(GTK_WINDOW (win), 
4651                                 TNY_FOLDER_STORE (dst_folder), xfer_messages_from_move_to_cb, dst_folder);
4652         }
4653         g_object_unref (account);
4654         g_object_unref (src_folder);
4655 }
4656
4657 void 
4658 modest_ui_actions_on_move_to (GtkAction *action, 
4659                               ModestWindow *win)
4660 {
4661         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4662         gint result = 0;
4663         TnyFolderStore *dst_folder = NULL;
4664         ModestMainWindow *main_window;
4665
4666         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4667                           MODEST_IS_MSG_VIEW_WINDOW (win));
4668
4669         /* Get the main window if exists */
4670         if (MODEST_IS_MAIN_WINDOW (win))
4671                 main_window = MODEST_MAIN_WINDOW (win);
4672         else
4673                 main_window = 
4674                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4675                                                                                FALSE)); /* don't create */
4676
4677         /* Get the folder view widget if exists */
4678         if (main_window)
4679                 folder_view = modest_main_window_get_child_widget (main_window,
4680                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4681         else
4682                 folder_view = NULL;
4683
4684         /* Create and run the dialog */
4685         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4686         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4687         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4688         result = gtk_dialog_run (GTK_DIALOG(dialog));
4689         g_object_ref (tree_view);
4690         gtk_widget_destroy (dialog);
4691
4692         if (result != GTK_RESPONSE_ACCEPT)
4693                 return;
4694
4695         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4696         /* Do window specific stuff */
4697         if (MODEST_IS_MAIN_WINDOW (win)) {
4698                 modest_ui_actions_on_main_window_move_to (action,
4699                                 folder_view,
4700                                 dst_folder,
4701                                 MODEST_MAIN_WINDOW (win));
4702         } else {
4703                 modest_ui_actions_on_msg_view_window_move_to (action,
4704                                 dst_folder,
4705                                 MODEST_MSG_VIEW_WINDOW (win));
4706         }
4707
4708         if (dst_folder)
4709                 g_object_unref (dst_folder);
4710 }
4711
4712 /*
4713  * Calls #HeadersFunc for each header already selected in the main
4714  * window or the message currently being shown in the msg view window
4715  */
4716 static void
4717 do_headers_action (ModestWindow *win, 
4718                    HeadersFunc func,
4719                    gpointer user_data)
4720 {
4721         TnyList *headers_list = NULL;
4722         TnyIterator *iter = NULL;
4723         TnyHeader *header = NULL;
4724         TnyFolder *folder = NULL;
4725
4726         /* Get headers */
4727         headers_list = get_selected_headers (win);
4728         if (!headers_list)
4729                 return;
4730
4731         /* Get the folder */
4732         iter = tny_list_create_iterator (headers_list);
4733         header = TNY_HEADER (tny_iterator_get_current (iter));
4734         if (header) {
4735                 folder = tny_header_get_folder (header);
4736                 g_object_unref (header);
4737         }
4738
4739         /* Call the function for each header */
4740         while (!tny_iterator_is_done (iter)) {
4741                 header = TNY_HEADER (tny_iterator_get_current (iter));
4742                 func (header, win, user_data);
4743                 g_object_unref (header);
4744                 tny_iterator_next (iter);
4745         }
4746
4747         /* Trick: do a poke status in order to speed up the signaling
4748            of observers */
4749         tny_folder_poke_status (folder);
4750
4751         /* Frees */
4752         g_object_unref (folder);
4753         g_object_unref (iter);
4754         g_object_unref (headers_list);
4755 }
4756
4757 void 
4758 modest_ui_actions_view_attachment (GtkAction *action,
4759                                    ModestWindow *window)
4760 {
4761         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4762                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4763         } else {
4764                 /* not supported window for this action */
4765                 g_return_if_reached ();
4766         }
4767 }
4768
4769 void
4770 modest_ui_actions_save_attachments (GtkAction *action,
4771                                     ModestWindow *window)
4772 {
4773         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4774                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4775         } else {
4776                 /* not supported window for this action */
4777                 g_return_if_reached ();
4778         }
4779 }
4780
4781 void
4782 modest_ui_actions_remove_attachments (GtkAction *action,
4783                                       ModestWindow *window)
4784 {
4785         if (MODEST_IS_MAIN_WINDOW (window)) {
4786                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4787         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4788                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4789         } else {
4790                 /* not supported window for this action */
4791                 g_return_if_reached ();
4792         }
4793 }
4794
4795 void 
4796 modest_ui_actions_on_settings (GtkAction *action, 
4797                                ModestWindow *win)
4798 {
4799         GtkWidget *dialog;
4800
4801         dialog = modest_platform_get_global_settings_dialog ();
4802         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4803         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4804         gtk_widget_show_all (dialog);
4805
4806         gtk_dialog_run (GTK_DIALOG (dialog));
4807
4808         gtk_widget_destroy (dialog);
4809 }
4810
4811 void 
4812 modest_ui_actions_on_help (GtkAction *action, 
4813                            GtkWindow *win)
4814 {
4815         const gchar *help_id;
4816
4817         g_return_if_fail (action);
4818         g_return_if_fail (win && GTK_IS_WINDOW(win));
4819         
4820         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
4821         
4822         if (help_id)
4823                 modest_platform_show_help (GTK_WINDOW (win), help_id);
4824         else
4825                 g_warning ("%s: no help for window %p", __FUNCTION__, win);
4826 }
4827
4828 static void
4829 retrieve_msg_contents_performer (gboolean canceled, 
4830                                  GError *err,
4831                                  GtkWindow *parent_window, 
4832                                  TnyAccount *account, 
4833                                  gpointer user_data)
4834 {
4835         ModestMailOperation *mail_op;
4836         TnyList *headers = TNY_LIST (user_data);
4837
4838         if (err || canceled) {
4839                 /* Show an error ? */
4840                 goto out;
4841         }
4842
4843         /* Create mail operation */
4844         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
4845                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4846                                                                  NULL, NULL);
4847         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4848         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4849
4850         /* Frees */
4851         g_object_unref (mail_op);
4852  out:
4853         g_object_unref (headers);
4854         g_object_unref (account);
4855 }
4856
4857 void 
4858 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4859                                             ModestWindow *window)
4860 {
4861         TnyList *headers = NULL;
4862         TnyAccount *account = NULL;
4863         TnyIterator *iter = NULL;
4864         TnyHeader *header = NULL;
4865         TnyFolder *folder = NULL;
4866
4867         /* Get headers */
4868         headers = get_selected_headers (window);
4869         if (!headers)
4870                 return;
4871
4872         /* Pick the account */
4873         iter = tny_list_create_iterator (headers);
4874         header = TNY_HEADER (tny_iterator_get_current (iter));
4875         folder = tny_header_get_folder (header);
4876         account = tny_folder_get_account (folder);
4877         g_object_unref (folder);
4878         g_object_unref (header);
4879         g_object_unref (iter);
4880
4881         /* Connect and perform the message retrieval */
4882         modest_platform_connect_and_perform ((GtkWindow *) window, 
4883                                              g_object_ref (account), 
4884                                              retrieve_msg_contents_performer, 
4885                                              g_object_ref (headers));
4886
4887         /* Frees */
4888         g_object_unref (account);
4889         g_object_unref (headers);
4890 }
4891
4892 void
4893 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4894                                           ModestWindow *window)
4895 {
4896         g_return_if_fail (MODEST_IS_WINDOW (window));
4897         
4898         /* Update dimmed */     
4899         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4900 }
4901
4902 void
4903 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4904                                           ModestWindow *window)
4905 {
4906         g_return_if_fail (MODEST_IS_WINDOW (window));
4907
4908         /* Update dimmed */     
4909         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4910 }
4911
4912 void
4913 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4914                                           ModestWindow *window)
4915 {
4916         g_return_if_fail (MODEST_IS_WINDOW (window));
4917
4918         /* Update dimmed */     
4919         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4920 }
4921
4922 void
4923 modest_ui_actions_on_format_menu_activated (GtkAction *action,
4924                                             ModestWindow *window)
4925 {
4926         g_return_if_fail (MODEST_IS_WINDOW (window));
4927
4928         /* Update dimmed */     
4929         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4930 }
4931
4932 void
4933 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4934                                           ModestWindow *window)
4935 {
4936         g_return_if_fail (MODEST_IS_WINDOW (window));
4937
4938         /* Update dimmed */     
4939         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4940 }
4941
4942 void
4943 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4944                                           ModestWindow *window)
4945 {
4946         g_return_if_fail (MODEST_IS_WINDOW (window));
4947
4948         /* Update dimmed */     
4949         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4950 }
4951
4952 void
4953 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4954                                                  ModestWindow *window)
4955 {
4956         g_return_if_fail (MODEST_IS_WINDOW (window));
4957
4958         /* Update dimmed */     
4959         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4960 }
4961
4962 void
4963 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4964                                                      ModestWindow *window)
4965 {
4966         g_return_if_fail (MODEST_IS_WINDOW (window));
4967
4968         /* Update dimmed */     
4969         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4970 }
4971
4972 void
4973 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4974                                                      ModestWindow *window)
4975 {
4976         g_return_if_fail (MODEST_IS_WINDOW (window));
4977
4978         /* Update dimmed */     
4979         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4980 }
4981
4982 void
4983 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4984 {
4985         g_return_if_fail (MODEST_IS_WINDOW (window));
4986
4987         /* Update dimmed */     
4988         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4989 }
4990
4991 void
4992 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4993 {
4994         g_return_if_fail (MODEST_IS_WINDOW (window));
4995
4996         modest_platform_show_search_messages (GTK_WINDOW (window));
4997 }
4998
4999 void     
5000 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5001 {
5002         g_return_if_fail (MODEST_IS_WINDOW (win));
5003         modest_platform_show_addressbook (GTK_WINDOW (win));
5004 }
5005
5006
5007 void
5008 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5009                                           ModestWindow *window)
5010 {
5011         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5012
5013         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5014 }
5015
5016 static void 
5017 on_send_receive_finished (ModestMailOperation  *mail_op, 
5018                            gpointer user_data)
5019 {
5020         GtkWidget *header_view, *folder_view;
5021         TnyFolderStore *folder_store;
5022         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5023
5024         /* Set send/receive operation finished */       
5025         modest_main_window_notify_send_receive_completed (main_win);
5026
5027         /* Don't refresh the current folder if there were any errors */
5028         if (modest_mail_operation_get_status (mail_op) !=
5029             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5030                 return;
5031         
5032         /* Refresh the current folder if we're viewing a window. We do
5033            this because the user won't be able to see the new mails in
5034            the selected folder after a Send&Receive because it only
5035            performs a poke_status, i.e, only the number of read/unread
5036            messages is updated, but the new headers are not
5037            downloaded */
5038         folder_view = modest_main_window_get_child_widget (main_win, 
5039                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5040         if (!folder_view)
5041                 return;
5042
5043         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5044         
5045         /* Do not need to refresh INBOX again because the
5046            update_account does it always automatically */
5047         if (folder_store && TNY_IS_FOLDER (folder_store) && 
5048             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5049                 ModestMailOperation *refresh_op;
5050
5051                 header_view = modest_main_window_get_child_widget (main_win,
5052                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5053                 
5054                 /* We do not need to set the contents style
5055                    because it hasn't changed. We also do not
5056                    need to save the widget status. Just force
5057                    a refresh */
5058                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5059                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5060                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5061                                                       folder_refreshed_cb, main_win);
5062                 g_object_unref (refresh_op);
5063         }
5064         
5065         if (folder_store)
5066                 g_object_unref (folder_store);
5067 }
5068
5069
5070 void 
5071 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
5072                                                 TnyHeader *header, 
5073                                                 TnyMsg *msg, 
5074                                                 GError *err, 
5075                                                 gpointer user_data)
5076 {
5077         const gchar* server_name = NULL;
5078         TnyTransportAccount *server_account;
5079         gchar *message = NULL;
5080
5081         /* Don't show anything if the user cancelled something */
5082         if (err->code == TNY_TRANSPORT_ACCOUNT_ERROR_SEND_USER_CANCEL)
5083                 return;
5084
5085         /* Get the server name: */
5086         server_account = 
5087                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
5088         if (server_account) {
5089                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
5090                         
5091                 g_object_unref (server_account);
5092                 server_account = NULL;
5093         }
5094         
5095         g_return_if_fail (server_name);
5096
5097         /* Show the appropriate message text for the GError: */
5098         switch (err->code) {
5099         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
5100                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5101                 break;
5102         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
5103                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5104                 break;
5105         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
5106                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
5107                 break;
5108         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
5109                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
5110                 break;
5111         default:
5112                 g_return_if_reached ();
5113         }
5114         
5115         /* TODO if the username or the password where not defined we
5116            should show the Accounts Settings dialog or the Connection
5117            specific SMTP server window */
5118
5119         modest_platform_run_information_dialog (NULL, message);
5120         g_free (message);
5121 }
5122
5123 void
5124 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5125                                                 gchar *msg_id, 
5126                                                 guint status,
5127                                                 gpointer user_data)
5128 {
5129         ModestMainWindow *main_window = NULL;
5130         ModestWindowMgr *mgr = NULL;
5131         GtkWidget *folder_view = NULL, *header_view = NULL;
5132         TnyFolderStore *selected_folder = NULL;
5133         TnyFolderType folder_type;
5134
5135         mgr = modest_runtime_get_window_mgr ();
5136         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
5137                                                                              FALSE));/* don't create */
5138         if (!main_window)
5139                 return;
5140
5141         /* Check if selected folder is OUTBOX */
5142         folder_view = modest_main_window_get_child_widget (main_window,
5143                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5144         header_view = modest_main_window_get_child_widget (main_window,
5145                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5146
5147         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5148         if (!TNY_IS_FOLDER (selected_folder)) 
5149                 goto frees;
5150
5151         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5152 #if GTK_CHECK_VERSION(2, 8, 0) 
5153         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
5154         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
5155                 GtkTreeViewColumn *tree_column;
5156
5157                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
5158                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5159                 gtk_tree_view_column_queue_resize (tree_column);
5160         }
5161 #else
5162         gtk_widget_queue_draw (header_view);
5163 #endif          
5164         
5165         /* Free */
5166  frees:
5167         if (selected_folder != NULL)
5168                 g_object_unref (selected_folder);
5169 }
5170
5171 void 
5172 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
5173                                                TnyAccount *account)
5174 {
5175         ModestTransportStoreProtocol proto;
5176         const gchar *proto_name;
5177         gchar *error_note = NULL;
5178         
5179         proto_name = tny_account_get_proto (account);
5180         proto = modest_protocol_info_get_transport_store_protocol (proto_name);
5181         
5182         switch (proto) {
5183         case MODEST_PROTOCOL_STORE_POP:
5184                 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"), 
5185                                               tny_account_get_hostname (account));
5186                 break;
5187         case MODEST_PROTOCOL_STORE_IMAP:
5188                 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"), 
5189                                               tny_account_get_hostname (account));
5190                 break;
5191         case MODEST_PROTOCOL_STORE_MAILDIR:
5192         case MODEST_PROTOCOL_STORE_MBOX:
5193                 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
5194                 break;
5195         default:
5196                 g_warning ("%s: This should not be reached", __FUNCTION__);
5197         }
5198
5199         if (error_note) {
5200                 modest_platform_run_information_dialog (parent_window, error_note);
5201                 g_free (error_note);
5202         }
5203 }