* Fixed some reference leaks
[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
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include <tny-mime-part.h>
48
49 #ifdef MODEST_PLATFORM_MAEMO
50 #include "maemo/modest-osso-state-saving.h"
51 #include "maemo/modest-maemo-utils.h"
52 #endif /* MODEST_PLATFORM_MAEMO */
53
54 #include "widgets/modest-ui-constants.h"
55 #include <widgets/modest-main-window.h>
56 #include <widgets/modest-msg-view-window.h>
57 #include <widgets/modest-account-view-window.h>
58 #include <widgets/modest-details-dialog.h>
59 #include <widgets/modest-attachments-view.h>
60 #include "widgets/modest-folder-view.h"
61 #include "widgets/modest-global-settings-dialog.h"
62 #include "modest-connection-specific-smtp-window.h"
63 #include "modest-account-mgr-helpers.h"
64 #include "modest-mail-operation.h"
65 #include "modest-text-utils.h"
66
67 #ifdef MODEST_HAVE_EASYSETUP
68 #include "easysetup/modest-easysetup-wizard.h"
69 #endif /* MODEST_HAVE_EASYSETUP */
70
71 #include <modest-widget-memory.h>
72 #include <tny-error.h>
73 #include <tny-simple-list.h>
74 #include <tny-msg-view.h>
75 #include <tny-device.h>
76 #include <tny-merge-folder.h>
77
78 #include <gtkhtml/gtkhtml.h>
79
80 typedef struct _GetMsgAsyncHelper {     
81         ModestWindow *window;
82         ModestMailOperation *mail_op;
83         TnyIterator *iter;
84         guint num_ops;
85         GFunc func;     
86         gpointer user_data;
87 } GetMsgAsyncHelper;
88
89 typedef enum _ReplyForwardAction {
90         ACTION_REPLY,
91         ACTION_REPLY_TO_ALL,
92         ACTION_FORWARD
93 } ReplyForwardAction;
94
95 typedef struct _ReplyForwardHelper {
96         guint reply_forward_type;
97         ReplyForwardAction action;
98         gchar *account_name;
99         GtkWidget *parent_window;
100 } ReplyForwardHelper;
101
102
103 /*
104  * The do_headers_action uses this kind of functions to perform some
105  * action to each member of a list of headers
106  */
107 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
108
109 static void     do_headers_action     (ModestWindow *win, 
110                                        HeadersFunc func,
111                                        gpointer user_data);
112
113 static void     open_msg_cb            (ModestMailOperation *mail_op, 
114                                         TnyHeader *header, 
115                                         TnyMsg *msg,
116                                         gpointer user_data);
117
118 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
119                                         TnyHeader *header, 
120                                         TnyMsg *msg,
121                                         gpointer user_data);
122
123 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
124
125 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
126                                         TnyFolder *folder, 
127                                         gpointer user_data);
128
129 static void     _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
130                                                    ModestMailOperationState *state,
131                                                    gpointer user_data);
132
133
134
135 static void
136 run_account_setup_wizard (ModestWindow *win)
137 {
138         ModestEasysetupWizardDialog *wizard;
139
140         g_return_if_fail (MODEST_IS_WINDOW(win));
141         
142         wizard = modest_easysetup_wizard_dialog_new ();
143         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
144         gtk_dialog_run (GTK_DIALOG (wizard));
145         gtk_widget_destroy (GTK_WIDGET (wizard));
146 }
147
148
149 void   
150 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
151 {
152         GtkWidget *about;
153         const gchar *authors[] = {
154                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
155                 NULL
156         };
157         about = gtk_about_dialog_new ();
158         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
159         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
160         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
161                                         _("Copyright (c) 2006, Nokia Corporation\n"
162                                           "All rights reserved."));
163         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
164                                        _("a modest e-mail client\n\n"
165                                          "design and implementation: Dirk-Jan C. Binnema\n"
166                                          "contributions from the fine people at KC and Ig\n"
167                                          "uses the tinymail email framework written by Philip van Hoof"));
168         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
169         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
170         
171         gtk_dialog_run (GTK_DIALOG (about));
172         gtk_widget_destroy(about);
173 }
174
175 /*
176  * Gets the list of currently selected messages. If the win is the
177  * main window, then it returns a newly allocated list of the headers
178  * selected in the header view. If win is the msg view window, then
179  * the value returned is a list with just a single header.
180  *
181  * The caller of this funcion must free the list.
182  */
183 static TnyList *
184 get_selected_headers (ModestWindow *win)
185 {
186         if (MODEST_IS_MAIN_WINDOW(win)) {
187                 GtkWidget *header_view;         
188                 
189                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
190                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
191                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
192                 
193         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
194                 /* for MsgViewWindows, we simply return a list with one element */
195                 TnyHeader *header;
196                 TnyList *list = NULL;
197                 
198                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
199                 if (header != NULL) {
200                         list = tny_simple_list_new ();
201                         tny_list_prepend (list, G_OBJECT(header));
202                         g_object_unref (G_OBJECT(header));
203                 }
204
205                 return list;
206
207         } else
208                 return NULL;
209 }
210
211 static void
212 headers_action_mark_as_read (TnyHeader *header,
213                              ModestWindow *win,
214                              gpointer user_data)
215 {
216         TnyHeaderFlags flags;
217
218         g_return_if_fail (TNY_IS_HEADER(header));
219
220         flags = tny_header_get_flags (header);
221         if (flags & TNY_HEADER_FLAG_SEEN) return;
222         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
223 }
224
225 static void
226 headers_action_mark_as_unread (TnyHeader *header,
227                                ModestWindow *win,
228                                gpointer user_data)
229 {
230         TnyHeaderFlags flags;
231
232         g_return_if_fail (TNY_IS_HEADER(header));
233
234         flags = tny_header_get_flags (header);
235         if (flags & TNY_HEADER_FLAG_SEEN)  {
236                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
237         }
238 }
239
240
241 static void
242 headers_action_delete (TnyHeader *header,
243                        ModestWindow *win,
244                        gpointer user_data)
245 {
246         ModestMailOperation *mail_op = NULL;
247
248         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, G_OBJECT(win));
249         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
250                                          mail_op);
251         
252         /* Always delete. TODO: Move to trash still not supported */
253         modest_mail_operation_remove_msg (mail_op, header, FALSE);
254         g_object_unref (G_OBJECT (mail_op));
255
256         /* refilter treemodel to hide marked-as-deleted rows */
257 /*      if (MODEST_IS_HEADER_VIEW (user_data)) */
258 /*              modest_header_view_refilter (MODEST_HEADER_VIEW (user_data)); */
259 }
260
261 /** After deleing a message that is currently visible in a window, 
262  * show the next message from the list, or close the window if there are no more messages.
263  **/
264 void modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
265 {
266         /* Close msg view window or select next */
267         if (modest_msg_view_window_last_message_selected (win) &&
268                 modest_msg_view_window_first_message_selected (win)) {
269                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
270         } else {
271                 modest_msg_view_window_select_next_message (win);
272         }
273 }
274
275 void
276 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
277 {
278         TnyList *header_list = NULL;
279         TnyIterator *iter = NULL;
280         TnyHeader *header = NULL;
281         gchar *message = NULL;
282         gchar *desc = NULL;
283         gint response;
284         ModestWindowMgr *mgr;
285         GtkWidget *header_view = NULL;
286
287         g_return_if_fail (MODEST_IS_WINDOW(win));
288         
289         /* Check first if the header view has the focus */
290         if (MODEST_IS_MAIN_WINDOW (win)) {
291                 header_view = 
292                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
293                                                              MODEST_WIDGET_TYPE_HEADER_VIEW);
294                 if (!gtk_widget_is_focus (header_view))
295                         return;
296         }
297         
298         header_list = get_selected_headers (win);
299         if (!header_list) return;
300
301         /* Check if any of the headers are already opened, or in the process of being opened */
302         if (MODEST_IS_MAIN_WINDOW (win)) {
303                 gboolean found;
304                 iter = tny_list_create_iterator (header_list);
305                 found = FALSE;
306                 mgr = modest_runtime_get_window_mgr ();
307                 while (!tny_iterator_is_done (iter) && !found) {
308                         header = TNY_HEADER (tny_iterator_get_current (iter));
309                         found =  modest_window_mgr_find_registered_header (mgr, header, NULL);
310                         g_object_unref (header);
311                         tny_iterator_next (iter);
312                 }
313                 g_object_unref (iter);
314
315                 if (found) {
316                         gchar *num, *msg;
317
318                         num = g_strdup_printf ("%d", tny_list_get_length (header_list));
319                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), num);
320
321                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
322                         
323                         g_free (msg);
324                         g_free (num);
325                         g_object_unref (header_list);
326                         return;
327                 }
328         }
329
330         /* Select message */
331         if (tny_list_get_length(header_list) == 1) {
332                 iter = tny_list_create_iterator (header_list);
333                 header = TNY_HEADER (tny_iterator_get_current (iter));
334                 desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
335                 g_object_unref (header);
336                 g_object_unref (iter);
337         }
338         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
339                                            tny_list_get_length(header_list)), desc);
340
341         /* Confirmation dialog */
342         printf("DEBUG: %s\n", __FUNCTION__);    
343         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
344                                                             message);
345         
346
347         if (response == GTK_RESPONSE_OK) {      
348                 ModestWindow *main_window = NULL;
349                 ModestWindowMgr *mgr = NULL;
350                 GtkTreeModel *model = NULL;
351                 GtkTreeSelection *sel = NULL;
352                 GList *sel_list = NULL, *tmp = NULL;
353                 GtkTreeRowReference *row_reference = NULL;
354                 GtkTreePath *next_path = NULL;
355
356                 /* Find last selected row */                    
357                 if (MODEST_IS_MAIN_WINDOW (win)) {
358                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
359                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
360                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
361                         for (tmp=sel_list; tmp; tmp=tmp->next) {
362                                 if (tmp->next == NULL) {
363                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
364                                         gtk_tree_path_next (next_path);
365                                         row_reference = gtk_tree_row_reference_new (model, next_path);
366                                         gtk_tree_path_free (next_path);
367                                 }
368                         }
369                 }
370                 
371                 /* Remove each header. If it's a view window header_view == NULL */
372                 do_headers_action (win, headers_action_delete, header_view);
373
374                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
375                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
376                         
377                         /* Get main window */
378                         mgr = modest_runtime_get_window_mgr ();
379                         main_window = modest_window_mgr_get_main_window (mgr);
380                 }
381                 else {                  
382                         /* Move cursor to next row */
383                         main_window = win; 
384
385                         /* Select next row */
386                         if (gtk_tree_row_reference_valid (row_reference)) {
387                                 next_path = gtk_tree_row_reference_get_path (row_reference);
388                                 gtk_tree_selection_select_path (sel, next_path);
389                                 gtk_tree_path_free (next_path);
390                         }
391                         if (row_reference != NULL)
392                                 gtk_tree_row_reference_free (row_reference);
393                 }
394
395                 /* Update toolbar dimming state */
396                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
397
398                 /* Free */
399                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
400                 g_list_free (sel_list);
401         }
402
403         /* Free*/
404         g_free(message);
405         g_free(desc);
406         g_object_unref (header_list);
407 }
408
409
410
411
412 /* delete either message or folder, based on where we are */
413 void
414 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
415 {
416         g_return_if_fail (MODEST_IS_WINDOW(win));
417         
418         /* Check first if the header view has the focus */
419         if (MODEST_IS_MAIN_WINDOW (win)) {
420                 GtkWidget *w;
421                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
422                                                          MODEST_WIDGET_TYPE_FOLDER_VIEW);
423                 if (gtk_widget_is_focus (w)) {
424                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
425                         return;
426                 }
427         }
428         modest_ui_actions_on_delete_message (action, win);
429 }
430
431
432
433 void
434 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
435 {
436 #ifdef MODEST_PLATFORM_MAEMO
437         modest_osso_save_state();
438 #endif /* MODEST_PLATFORM_MAEMO */
439
440         g_debug ("closing down, clearing %d item(s) from operation queue",
441                  modest_mail_operation_queue_num_elements
442                  (modest_runtime_get_mail_operation_queue()));
443
444         /* cancel all outstanding operations */
445         modest_mail_operation_queue_cancel_all 
446                 (modest_runtime_get_mail_operation_queue());
447         
448         g_debug ("queue has been cleared");
449
450         /* note: when modest-tny-account-store is finalized,
451            it will automatically set all network connections
452            to offline */
453
454         gtk_main_quit ();
455 }
456
457 void
458 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
459 {
460         gboolean ret_value;
461         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
462
463 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
464 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
465 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
466 /*              gboolean ret_value; */
467 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
468 /*      } else if (MODEST_IS_WINDOW (win)) { */
469 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
470 /*      } else { */
471 /*              g_return_if_reached (); */
472 /*      } */
473 }
474
475 void
476 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
477 {
478         GtkClipboard *clipboard = NULL;
479         gchar *selection = NULL;
480
481         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
482         selection = gtk_clipboard_wait_for_text (clipboard);
483
484         /* Question: why is the clipboard being used here? 
485          * It doesn't really make a lot of sense. */
486
487         if (selection)
488         {
489                 modest_address_book_add_address (selection);
490                 g_free (selection);
491         }
492 }
493
494 void
495 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
496 {
497         /* This is currently only implemented for Maemo */
498 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
499         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
500                 run_account_setup_wizard (win);
501                 return;
502         } else  {
503                 /* Show the list of accounts: */
504                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
505                 modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), account_win); 
506         }
507 #else
508         GtkWidget *dialog, *label;
509         
510         /* Create the widgets */
511         
512         dialog = gtk_dialog_new_with_buttons ("Message",
513                                               GTK_WINDOW(win),
514                                               GTK_DIALOG_DESTROY_WITH_PARENT,
515                                               GTK_STOCK_OK,
516                                               GTK_RESPONSE_NONE,
517                                               NULL);
518         label = gtk_label_new ("Hello World!");
519         
520         /* Ensure that the dialog box is destroyed when the user responds. */
521         
522         g_signal_connect_swapped (dialog, "response", 
523                                   G_CALLBACK (gtk_widget_destroy),
524                                   dialog);
525         
526         /* Add the label, and show everything we've added to the dialog. */
527         
528         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
529                            label);
530         gtk_widget_show_all (dialog);
531 #endif /* MODEST_PLATFORM_MAEMO */
532 }
533
534 static void
535 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
536 {
537         ModestWindow *main_window = MODEST_WINDOW (user_data);
538         
539         /* Save any changes. */
540         modest_connection_specific_smtp_window_save_server_accounts (
541                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window), 
542                         modest_window_get_active_account (main_window));
543         gtk_widget_destroy (GTK_WIDGET (window));
544 }
545
546
547
548 void
549 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
550 {
551         /* This is currently only implemented for Maemo,
552          * because it requires an API (libconic) to detect different connection 
553          * possiblities.
554          */
555 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
556         
557         /* Create the window if necessary: */
558         const gchar *active_account_name = modest_window_get_active_account (win);
559         
560         /* TODO: Dim the menu item (not in the UI spec)? or show a warning,
561          * or show the default account?
562          * If we show the default account then the account name should be shown in 
563          * the window when we show it. */
564         if (!active_account_name) {
565                 g_warning ("%s: No account is active.", __FUNCTION__);
566                 return;
567         }
568                 
569         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
570         modest_connection_specific_smtp_window_fill_with_connections (
571                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
572                 modest_runtime_get_account_mgr(), 
573                 active_account_name);
574
575         /* Show the window: */  
576         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
577         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
578         gtk_widget_show (specific_window);
579     
580         /* Save changes when the window is hidden: */
581         g_signal_connect (specific_window, "hide", 
582                 G_CALLBACK (on_smtp_servers_window_hide), win);
583 #endif /* MODEST_PLATFORM_MAEMO */
584 }
585
586 void
587 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
588 {
589         ModestWindow *msg_win = NULL;
590         TnyMsg *msg = NULL;
591         TnyFolder *folder = NULL;
592         gchar *account_name = NULL;
593         gchar *from_str = NULL;
594 /*      GError *err = NULL; */
595         TnyAccount *account = NULL;
596         ModestWindowMgr *mgr;
597         gchar *signature = NULL, *blank_and_signature = NULL;
598
599         /* if there are no accounts yet, just show the wizard */
600         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
601                         run_account_setup_wizard (win);
602                         return;
603         }
604         
605         account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
606         if (!account_name)
607                 account_name = g_strdup (modest_window_get_active_account (win));
608         if (!account_name) {
609                 g_printerr ("modest: no account found\n");
610                 goto cleanup;
611         }
612         
613         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
614                                                                        account_name,
615                                                                        TNY_ACCOUNT_TYPE_STORE);
616         if (!account) {
617                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
618                 goto cleanup;
619         }
620
621         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
622         if (!from_str) {
623                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
624                 goto cleanup;
625         }
626
627         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr (), account_name,
628                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
629                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), account_name,
630                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
631                 blank_and_signature = g_strconcat ("\n", signature, NULL);
632                 g_free (signature);
633         } else {
634                 blank_and_signature = g_strdup ("");
635         }
636
637         msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
638         if (!msg) {
639                 g_printerr ("modest: failed to create new msg\n");
640                 goto cleanup;
641         }
642         
643         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
644         if (!folder) {
645                 g_printerr ("modest: failed to find Drafts folder\n");
646                 goto cleanup;
647         }
648         
649
650         /* Create and register edit window */
651         /* This is destroyed by TOOD. */
652         msg_win = modest_msg_edit_window_new (msg, account_name);
653         mgr = modest_runtime_get_window_mgr ();
654         modest_window_mgr_register_window (mgr, msg_win);
655
656         if (win)
657                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
658                                               GTK_WINDOW (win));        
659         gtk_widget_show_all (GTK_WIDGET (msg_win));
660
661 cleanup:
662         g_free (account_name);
663         g_free (from_str);
664         g_free (blank_and_signature);
665         if (msg_win)
666                 g_object_unref (msg_win);
667         if (account)
668                 g_object_unref (G_OBJECT(account));
669         if (msg)
670                 g_object_unref (G_OBJECT(msg));
671         if (folder)
672                 g_object_unref (G_OBJECT(folder));
673 }
674
675 gboolean 
676 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
677                                        TnyHeader *header,
678                                        TnyMsg *msg)
679 {
680         ModestMailOperationStatus status;
681
682         /* If there is no message or the operation was not successful */
683         status = modest_mail_operation_get_status (mail_op);
684         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
685
686                 /* Remove the header from the preregistered uids */
687                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
688                                                      header);
689
690                 return FALSE;
691         }
692
693         return TRUE;
694 }
695
696 static void
697 open_msg_cb (ModestMailOperation *mail_op, 
698              TnyHeader *header, 
699              TnyMsg *msg, 
700              gpointer user_data)
701 {
702         ModestWindowMgr *mgr = NULL;
703         ModestWindow *parent_win = NULL;
704         ModestWindow *win = NULL;
705         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
706         gchar *account = NULL;
707         TnyFolder *folder;
708         
709         /* Do nothing if there was any problem with the mail
710            operation. The error will be shown by the error_handler of
711            the mail operation */
712         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
713                 return;
714         }
715
716         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
717         folder = tny_header_get_folder (header);
718
719         /* Mark header as read */
720         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
721
722         /* Get account */
723         account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
724         if (!account)
725                 account =  g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
726         
727         /* Gets folder type (OUTBOX headers will be opened in edit window */
728         if (modest_tny_folder_is_local_folder (folder))
729                 folder_type = modest_tny_folder_get_local_folder_type (folder);
730
731         /* If the header is in the drafts folder then open the editor,
732            else the message view window */
733         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
734                 /* we cannot edit without a valid account... */
735                 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
736                         run_account_setup_wizard(parent_win);
737                         goto cleanup;
738                 }
739                 win = modest_msg_edit_window_new (msg, account);
740         } else {
741                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
742                 
743                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
744                         GtkWidget *header_view;
745                         GtkTreeSelection *sel;
746                         GList *sel_list = NULL;
747                         GtkTreeModel *model;
748                         
749                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
750                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
751
752                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
753                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
754
755                         if (sel_list != NULL) {
756                                 GtkTreeRowReference *row_reference;
757
758                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
759                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
760                                 g_list_free (sel_list);
761                                 
762                                 win = modest_msg_view_window_new_with_header_model (msg, 
763                                                                                     account,
764                                                                                     (const gchar*) uid,
765                                                                                     model, 
766                                                                                     row_reference);
767                                 gtk_tree_row_reference_free (row_reference);
768                         } else {
769                                 win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
770                         }
771                 } else {
772                         win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
773                 }
774                 g_free (uid);
775         }
776         
777         /* Register and show new window */
778         if (win != NULL) {
779                 mgr = modest_runtime_get_window_mgr ();
780                 modest_window_mgr_register_window (mgr, win);
781                 g_object_unref (win);
782                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
783                 gtk_widget_show_all (GTK_WIDGET(win));
784         }
785
786         /* Update toolbar dimming state */
787         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
788                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
789         }
790
791 cleanup:
792         /* Free */
793         g_free(account);
794         g_object_unref (parent_win);
795         g_object_unref (folder);
796 }
797
798 void
799 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
800                                                gpointer user_data)
801 {
802         const GError *error;
803         GObject *win = modest_mail_operation_get_source (mail_op);
804
805         error = modest_mail_operation_get_error (mail_op);
806         printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, error->code, error->message);
807  
808         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
809
810                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
811                                                         error->message);
812         } else {
813                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
814                                                         _("mail_ni_ui_folder_get_msg_folder_error"));
815         }
816
817         if (win)
818                 g_object_unref (win);
819 }
820
821 /*
822  * This function is used by both modest_ui_actions_on_open and
823  * modest_ui_actions_on_header_activated. This way we always do the
824  * same when trying to open messages.
825  */
826 static void
827 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
828 {
829         ModestWindowMgr *mgr = NULL;
830         TnyIterator *iter = NULL;
831         ModestMailOperation *mail_op1 = NULL;
832         ModestMailOperation *mail_op2 = NULL;
833         TnyList *not_opened_headers = NULL;
834         TnyList *not_opened_cached_headers = NULL;
835         TnyHeaderFlags flags;
836                 
837         /* Look if we already have a message view for each header. If
838            true, then remove the header from the list of headers to
839            open */
840         mgr = modest_runtime_get_window_mgr ();
841         iter = tny_list_create_iterator (headers);
842         not_opened_headers = tny_simple_list_new ();
843         not_opened_cached_headers = tny_simple_list_new ();
844         while (!tny_iterator_is_done (iter)) {
845
846                 ModestWindow *window;
847                 TnyHeader *header;
848                 gboolean found;
849                 
850                 header = TNY_HEADER (tny_iterator_get_current (iter));
851                 flags = tny_header_get_flags (header);
852
853                 window = NULL;
854                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
855                 
856                 /* Do not open again the message and present the
857                    window to the user */
858                 if (found) {
859                         if (window)
860                                 gtk_window_present (GTK_WINDOW (window));
861                         else
862                                 /* the header has been registered already, we don't do
863                                  * anything but wait for the window to come up*/
864                                 g_warning ("debug: header %p already registered, waiting for window",
865                                            header);
866                 } else {
867                         if (!(flags & TNY_HEADER_FLAG_CACHED))
868                                 tny_list_append (not_opened_headers, G_OBJECT (header));
869                         /* Check if msg has already been retreived */
870                         else
871                                 tny_list_append (not_opened_cached_headers, G_OBJECT (header));
872                 }
873                 g_object_unref (header);
874                 tny_iterator_next (iter);
875         }
876         g_object_unref (iter);
877         iter = NULL;
878         
879         /* If some messages would have to be downloaded, ask the user to 
880          * make a connection. It's generally easier to do this here (in the mainloop) 
881          * than later in a thread:
882          */
883         if (tny_list_get_length (not_opened_cached_headers) > 0) {
884                 gboolean connected = modest_platform_connect_and_wait (GTK_WINDOW (win));
885                 
886                 /* Don't go further if a connection would be necessary but none is available: */
887                 if (!connected) {
888                         g_object_unref (not_opened_headers);
889                         g_object_unref (not_opened_cached_headers);
890                         return;
891                 }
892         }
893         
894         /* Register the headers before actually creating the windows: */
895         TnyIterator *iter_not_opened = tny_list_create_iterator (not_opened_headers);
896         while (!tny_iterator_is_done (iter_not_opened)) {
897                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
898                 modest_window_mgr_register_header (mgr, header);
899                 g_object_unref (header);
900                 
901                 tny_iterator_next (iter_not_opened);
902         }
903         g_object_unref (iter_not_opened);
904         iter_not_opened = NULL;
905         
906         TnyIterator *iter_cached = tny_list_create_iterator (not_opened_cached_headers);
907         while (!tny_iterator_is_done (iter_cached)) {
908                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_cached));
909                 modest_window_mgr_register_header (mgr, header);
910                 g_object_unref (header);
911                 
912                 tny_iterator_next (iter_cached);
913         }
914         g_object_unref (iter_cached);
915         iter_cached = NULL;
916         
917         
918         /* Open each uncached message */
919         if (tny_list_get_length (not_opened_headers) > 0) {
920                 mail_op1 = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
921                                                                          G_OBJECT (win), 
922                                                                          modest_ui_actions_get_msgs_full_error_handler, 
923                                                                          NULL);
924                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op1);
925                 if (tny_list_get_length (not_opened_headers) > 1) {
926                         modest_mail_operation_get_msgs_full (mail_op1, 
927                                                              not_opened_headers, 
928                                                              open_msg_cb, 
929                                                              NULL, 
930                                                              NULL);
931                 } else {
932                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
933                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
934                         modest_mail_operation_get_msg (mail_op1, header, open_msg_cb, NULL);
935                         g_object_unref (header);
936                         g_object_unref (iter);
937                 }
938         }
939
940         /* Open each cached message */
941         if (tny_list_get_length (not_opened_cached_headers) > 0) {
942                 mail_op2 = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
943                                                                          G_OBJECT (win), 
944                                                                          modest_ui_actions_get_msgs_full_error_handler, 
945                                                                          NULL);
946                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op2);
947                 if (tny_list_get_length (not_opened_cached_headers) > 1) {
948                         modest_mail_operation_get_msgs_full (mail_op2, 
949                                                              not_opened_headers, 
950                                                              open_msg_cb, 
951                                                              NULL, 
952                                                              NULL);
953                 } else {
954                         TnyIterator *iter = tny_list_create_iterator (not_opened_cached_headers);
955                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
956                         modest_mail_operation_get_msg (mail_op2, header, open_msg_cb, NULL);
957                         g_object_unref (header);
958                         g_object_unref (iter);
959                 }
960         }
961
962         /* Clean */
963         if (not_opened_headers != NULL)
964                 g_object_unref (not_opened_headers);
965         if (not_opened_cached_headers != NULL)
966                 g_object_unref (not_opened_cached_headers);
967         if (iter != NULL) 
968                 g_object_unref (iter);
969         if (mail_op1 != NULL)
970                 g_object_unref (mail_op1);
971         if (mail_op2 != NULL) 
972                 g_object_unref (mail_op2);
973 }
974
975 void
976 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
977 {
978         TnyList *headers;
979
980         /* Get headers */
981         headers = get_selected_headers (win);
982         if (!headers)
983                 return;
984
985         /* Open them */
986         _modest_ui_actions_open (headers, win);
987
988         g_object_unref(headers);
989 }
990
991
992 static void
993 free_reply_forward_helper (gpointer data)
994 {
995         ReplyForwardHelper *helper;
996
997         helper = (ReplyForwardHelper *) data;
998         g_free (helper->account_name);
999         g_slice_free (ReplyForwardHelper, helper);
1000 }
1001
1002 static void
1003 reply_forward_cb (ModestMailOperation *mail_op, 
1004                   TnyHeader *header, 
1005                   TnyMsg *msg,
1006                   gpointer user_data)
1007 {
1008         TnyMsg *new_msg;
1009         ReplyForwardHelper *rf_helper;
1010         ModestWindow *msg_win = NULL;
1011         ModestEditType edit_type;
1012         gchar *from = NULL;
1013         TnyAccount *account = NULL;
1014         ModestWindowMgr *mgr = NULL;
1015         gchar *signature = NULL;
1016
1017         /* If there was any error. The mail operation could be NULL,
1018            this means that we already have the message downloaded and
1019            that we didn't do a mail operation to retrieve it */
1020         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1021                 return;
1022                         
1023         g_return_if_fail (user_data != NULL);
1024         rf_helper = (ReplyForwardHelper *) user_data;
1025
1026         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1027                                                    rf_helper->account_name);
1028         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
1029                                          rf_helper->account_name,
1030                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
1031                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
1032                                                            rf_helper->account_name,
1033                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
1034         }
1035
1036         /* Create reply mail */
1037         switch (rf_helper->action) {
1038         case ACTION_REPLY:
1039                 new_msg = 
1040                         modest_tny_msg_create_reply_msg (msg,  from, signature,
1041                                                          rf_helper->reply_forward_type,
1042                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1043                 break;
1044         case ACTION_REPLY_TO_ALL:
1045                 new_msg = 
1046                         modest_tny_msg_create_reply_msg (msg, from, signature, rf_helper->reply_forward_type,
1047                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1048                 edit_type = MODEST_EDIT_TYPE_REPLY;
1049                 break;
1050         case ACTION_FORWARD:
1051                 new_msg = 
1052                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1053                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1054                 break;
1055         default:
1056                 g_return_if_reached ();
1057                 return;
1058         }
1059
1060         g_free (signature);
1061
1062         if (!new_msg) {
1063                 g_printerr ("modest: failed to create message\n");
1064                 goto cleanup;
1065         }
1066
1067         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1068                                                                        rf_helper->account_name,
1069                                                                        TNY_ACCOUNT_TYPE_STORE);
1070         if (!account) {
1071                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1072                 goto cleanup;
1073         }
1074
1075         /* Create and register the windows */
1076         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
1077         mgr = modest_runtime_get_window_mgr ();
1078         modest_window_mgr_register_window (mgr, msg_win);
1079
1080         if (rf_helper->parent_window != NULL) {
1081                 gdouble parent_zoom;
1082
1083                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1084                 modest_window_set_zoom (msg_win, parent_zoom);
1085         }
1086
1087         /* Show edit window */
1088         gtk_widget_show_all (GTK_WIDGET (msg_win));
1089
1090 cleanup:
1091         if (msg_win)
1092                 g_object_unref (msg_win);
1093         if (new_msg)
1094                 g_object_unref (G_OBJECT (new_msg));
1095         if (account)
1096                 g_object_unref (G_OBJECT (account));
1097 /*      g_object_unref (msg); */
1098         g_object_unref (header);
1099         free_reply_forward_helper (rf_helper);
1100 }
1101
1102 /*
1103  * Checks a list of headers. If any of them are not currently
1104  * downloaded (CACHED) then it asks the user for permission to
1105  * download them.
1106  *
1107  * Returns FALSE if the user does not want to download the
1108  * messages. Returns TRUE if the user allowed the download or if all
1109  * of them are currently downloaded
1110  */
1111 static gboolean
1112 download_uncached_messages (TnyList *header_list, GtkWindow *win,
1113                             gboolean reply_fwd)
1114 {
1115         TnyIterator *iter;
1116         gboolean retval;
1117         gint uncached_messages = 0;
1118
1119         iter = tny_list_create_iterator (header_list);
1120         while (!tny_iterator_is_done (iter)) {
1121                 TnyHeader *header;
1122                 TnyHeaderFlags flags;
1123
1124                 header = TNY_HEADER (tny_iterator_get_current (iter));
1125                 flags = tny_header_get_flags (header);
1126                 /* TODO: is this the right flag?, it seems that some
1127                    headers that have been previously downloaded do not
1128                    come with it */
1129                 if (! (flags & TNY_HEADER_FLAG_CACHED))
1130                         uncached_messages ++;
1131                 g_object_unref (header);
1132                 tny_iterator_next (iter);
1133         }
1134         g_object_unref (iter);
1135
1136         /* Ask for user permission to download the messages */
1137         retval = TRUE;
1138         if (uncached_messages > 0) {
1139                 GtkResponseType response;
1140                 if (reply_fwd)
1141                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1142                                                                             _("emev_nc_include_original"));
1143                 else
1144                         response =
1145                                 modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1146                                                                          ngettext("mcen_nc_get_msg",
1147                                                                                   "mcen_nc_get_msgs",
1148                                                                                   uncached_messages));
1149                 if (response == GTK_RESPONSE_CANCEL)
1150                         retval = FALSE;
1151                 else {
1152                         /* If a download will be necessary, make sure that we have a connection: */
1153                         retval = modest_platform_connect_and_wait(win); 
1154                 }
1155         }
1156         return retval;
1157 }
1158
1159
1160 /*
1161  * Common code for the reply and forward actions
1162  */
1163 static void
1164 reply_forward (ReplyForwardAction action, ModestWindow *win)
1165 {
1166         ModestMailOperation *mail_op = NULL;
1167         TnyList *header_list = NULL;
1168         ReplyForwardHelper *rf_helper = NULL;
1169         guint reply_forward_type;
1170         gboolean continue_download;
1171         
1172         g_return_if_fail (MODEST_IS_WINDOW(win));
1173
1174         /* we need an account when editing */
1175         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1176                 run_account_setup_wizard (win);
1177                 return;
1178         }
1179         
1180         header_list = get_selected_headers (win);
1181         if (!header_list)
1182                 return;
1183
1184         /* Check that the messages have been previously downloaded */
1185         continue_download = download_uncached_messages (header_list, GTK_WINDOW (win), TRUE);
1186         if (!continue_download) {
1187                 g_object_unref (header_list);
1188                 return;
1189         }
1190         
1191         reply_forward_type = 
1192                 modest_conf_get_int (modest_runtime_get_conf (),
1193                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1194                                      NULL);
1195         /* We assume that we can only select messages of the
1196            same folder and that we reply all of them from the
1197            same account. In fact the interface currently only
1198            allows single selection */
1199         
1200         /* Fill helpers */
1201         rf_helper = g_slice_new0 (ReplyForwardHelper);
1202         rf_helper->reply_forward_type = reply_forward_type;
1203         rf_helper->action = action;
1204         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1205         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1206                 rf_helper->parent_window = GTK_WIDGET (win);
1207         if (!rf_helper->account_name)
1208                 rf_helper->account_name =
1209                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1210
1211         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1212                 TnyMsg *msg;
1213                 TnyHeader *header;
1214                 /* Get header and message. Do not free them here, the
1215                    reply_forward_cb must do it */
1216                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1217                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1218                 if (!msg || !header) {
1219                         if (msg)
1220                                 g_object_unref (msg);
1221                         if (header)
1222                                 g_object_unref (header);
1223                         g_printerr ("modest: no message found\n");
1224                         return;
1225                 } else {
1226                         reply_forward_cb (NULL, header, msg, rf_helper);
1227                 }
1228         } else {
1229                 TnyHeader *header;
1230                 TnyIterator *iter;
1231
1232                 /* Retrieve messages */
1233                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1234                                                                          G_OBJECT(win),
1235                                                                          modest_ui_actions_get_msgs_full_error_handler, 
1236                                                                          NULL);
1237                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1238
1239                 /* Only reply/forward to one message */
1240                 iter = tny_list_create_iterator (header_list);
1241                 header = TNY_HEADER (tny_iterator_get_current (iter));
1242                 g_object_unref (iter);
1243
1244                 modest_mail_operation_get_msg (mail_op,
1245                                                header,
1246                                                reply_forward_cb,
1247                                                rf_helper);
1248
1249 /*              modest_mail_operation_get_msgs_full (mail_op,  */
1250 /*                                                   header_list,  */
1251 /*                                                   reply_forward_cb,  */
1252 /*                                                   rf_helper,  */
1253 /*                                                   free_reply_forward_helper); */
1254
1255                 /* Clean */
1256                 g_object_unref(mail_op);
1257         }
1258
1259         /* Free */
1260         g_object_unref (header_list);
1261 }
1262
1263 void
1264 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1265 {
1266         g_return_if_fail (MODEST_IS_WINDOW(win));
1267
1268         reply_forward (ACTION_REPLY, win);
1269 }
1270
1271 void
1272 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1273 {
1274         g_return_if_fail (MODEST_IS_WINDOW(win));
1275
1276         reply_forward (ACTION_FORWARD, win);
1277 }
1278
1279 void
1280 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1281 {
1282         g_return_if_fail (MODEST_IS_WINDOW(win));
1283
1284         reply_forward (ACTION_REPLY_TO_ALL, win);
1285 }
1286
1287 void 
1288 modest_ui_actions_on_next (GtkAction *action, 
1289                            ModestWindow *window)
1290 {
1291         if (MODEST_IS_MAIN_WINDOW (window)) {
1292                 GtkWidget *header_view;
1293
1294                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1295                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1296                 if (!header_view)
1297                         return;
1298         
1299                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
1300         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1301                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
1302         } else {
1303                 g_return_if_reached ();
1304         }
1305 }
1306
1307 void 
1308 modest_ui_actions_on_prev (GtkAction *action, 
1309                            ModestWindow *window)
1310 {
1311         g_return_if_fail (MODEST_IS_WINDOW(window));
1312
1313         if (MODEST_IS_MAIN_WINDOW (window)) {
1314                 GtkWidget *header_view;
1315                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1316                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1317                 if (!header_view)
1318                         return;
1319                 
1320                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1321         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1322                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1323         } else {
1324                 g_return_if_reached ();
1325         }
1326 }
1327
1328 void 
1329 modest_ui_actions_on_sort (GtkAction *action, 
1330                            ModestWindow *window)
1331 {
1332         g_return_if_fail (MODEST_IS_WINDOW(window));
1333
1334         if (MODEST_IS_MAIN_WINDOW (window)) {
1335                 GtkWidget *header_view;
1336                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1337                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1338                 if (!header_view)
1339                         return;
1340
1341                 /* Show sorting dialog */
1342                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1343         }
1344 }
1345
1346 static void
1347 new_messages_arrived (ModestMailOperation *self, 
1348                       gint new_messages,
1349                       gpointer user_data)
1350 {
1351         if (new_messages == 0)
1352                 return;
1353
1354         modest_platform_on_new_msg ();
1355 }
1356
1357 /*
1358  * This function performs the send & receive required actions. The
1359  * window is used to create the mail operation. Typically it should
1360  * always be the main window, but we pass it as argument in order to
1361  * be more flexible.
1362  */
1363 void
1364 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1365 {
1366         gchar *acc_name = NULL;
1367         ModestMailOperation *mail_op;
1368
1369         /* If no account name was provided then get the current account, and if
1370            there is no current account then pick the default one: */
1371         if (!account_name) {
1372                 acc_name = g_strdup (modest_window_get_active_account(win));
1373                 if (!acc_name)
1374                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1375                 if (!acc_name) {
1376                         g_printerr ("modest: cannot get default account\n");
1377                         return;
1378                 }
1379         } else {
1380                 acc_name = g_strdup (account_name);
1381         }
1382
1383         /* Set send/receive operation in progress */    
1384         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1385
1386         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1387                                                                  G_OBJECT (win),
1388                                                                  modest_ui_actions_send_receive_error_handler,
1389                                                                  NULL);
1390
1391         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1392                           G_CALLBACK (_on_send_receive_progress_changed), 
1393                           win);
1394
1395         /* Send & receive. */
1396         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1397         /* Receive and then send. The operation is tagged initially as
1398            a receive operation because the account update performs a
1399            receive and then a send. The operation changes its type
1400            internally, so the progress objects will receive the proper
1401            progress information */
1402         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1403         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, NULL);
1404         g_object_unref (G_OBJECT (mail_op));
1405         
1406         /* Free */
1407         g_free (acc_name);
1408 }
1409
1410
1411 static void
1412 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1413                                   ModestWindow *win)
1414 {
1415         TnyTransportAccount *transport_account;
1416         TnySendQueue *send_queue = NULL;
1417         GError *error = NULL;
1418
1419         /* Get transport account */
1420         transport_account =
1421                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1422                                       (modest_runtime_get_account_store(),
1423                                        account_name,
1424                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1425         if (!transport_account) {
1426                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1427                 goto frees;
1428         }
1429
1430         /* Get send queue*/
1431         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1432         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1433                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1434                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1435                              "modest: could not find send queue for account\n");
1436         } else {
1437                 /* Keeep messages in outbox folder */
1438                 tny_send_queue_cancel (send_queue, FALSE, &error);
1439         }       
1440
1441  frees:
1442         if (transport_account != NULL) 
1443                 g_object_unref (G_OBJECT (transport_account));
1444 }
1445
1446 static void
1447 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1448 {
1449         GSList *account_names, *iter;
1450
1451         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1452                                                           TRUE);
1453
1454         iter = account_names;
1455         while (iter) {                  
1456                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1457                 iter = g_slist_next (iter);
1458         }
1459
1460         modest_account_mgr_free_account_names (account_names);
1461         account_names = NULL;
1462 }
1463
1464 void
1465 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1466
1467 {
1468         /* Check if accounts exist */
1469         gboolean accounts_exist = 
1470                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1471         
1472         /* If not, allow the user to create an account before trying to send/receive. */
1473         if (!accounts_exist)
1474                 modest_ui_actions_on_accounts (NULL, win);
1475         
1476         /* Cancel all sending operaitons */     
1477         modest_ui_actions_cancel_send_all (win);
1478 }
1479
1480 /*
1481  * Refreshes all accounts. This function will be used by automatic
1482  * updates
1483  */
1484 void
1485 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1486 {
1487         GSList *account_names, *iter;
1488
1489         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1490                                                           TRUE);
1491
1492         iter = account_names;
1493         while (iter) {                  
1494                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1495                 iter = g_slist_next (iter);
1496         }
1497
1498         modest_account_mgr_free_account_names (account_names);
1499         account_names = NULL;
1500 }
1501
1502 /*
1503  * Handler of the click on Send&Receive button in the main toolbar
1504  */
1505 void
1506 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
1507 {
1508         /* Check if accounts exist */
1509         gboolean accounts_exist = 
1510                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1511         
1512         /* If not, allow the user to create an account before trying to send/receive. */
1513         if (!accounts_exist)
1514                 modest_ui_actions_on_accounts (NULL, win);
1515
1516         /* Refresh currently selected folder. Note that if we only
1517            want to retrive the headers, then the refresh only will
1518            invoke a poke_status over all folders, i.e., only the
1519            total/unread count will be updated */
1520         if (MODEST_IS_MAIN_WINDOW (win)) {
1521                 GtkWidget *header_view, *folder_view;
1522                 TnyFolderStore *folder_store;
1523
1524                 /* Get folder and header view */
1525                 folder_view = 
1526                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1527                                                              MODEST_WIDGET_TYPE_FOLDER_VIEW);
1528
1529                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1530
1531                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1532                         header_view = 
1533                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1534                                                                      MODEST_WIDGET_TYPE_HEADER_VIEW);
1535                 
1536                         /* We do not need to set the contents style
1537                            because it hasn't changed. We also do not
1538                            need to save the widget status. Just force
1539                            a refresh */
1540                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1541                                                        TNY_FOLDER (folder_store),
1542                                                        folder_refreshed_cb,
1543                                                        MODEST_MAIN_WINDOW (win));
1544                 }
1545                 
1546                 if (folder_store)
1547                         g_object_unref (folder_store);
1548         }
1549         
1550         /* Refresh the active account */
1551         modest_ui_actions_do_send_receive (NULL, win);
1552 }
1553
1554
1555 void
1556 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1557 {
1558         ModestConf *conf;
1559         GtkWidget *header_view;
1560         
1561         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1562
1563         header_view = modest_main_window_get_child_widget (main_window,
1564                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1565         if (!header_view)
1566                 return;
1567
1568         conf = modest_runtime_get_conf ();
1569         
1570         /* what is saved/restored is depending on the style; thus; we save with
1571          * old style, then update the style, and restore for this new style
1572          */
1573         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1574         
1575         if (modest_header_view_get_style
1576             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1577                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1578                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1579         else
1580                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1581                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1582
1583         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1584                                       MODEST_CONF_HEADER_VIEW_KEY);
1585 }
1586
1587
1588 void 
1589 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1590                                       TnyHeader *header,
1591                                       ModestMainWindow *main_window)
1592 {
1593         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1594         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1595         
1596         /* If no header has been selected then exit */
1597         if (!header)
1598                 return;
1599
1600         /* Update focus */
1601         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1602             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1603
1604         /* Update Main window title */
1605         if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
1606                 const gchar *subject = tny_header_get_subject (header);
1607                 if (subject && strlen(subject) > 0)
1608                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
1609                 else
1610                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
1611         }
1612
1613         /* Update toolbar dimming state */
1614         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1615 }
1616
1617 void
1618 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1619                                        TnyHeader *header,
1620                                        ModestMainWindow *main_window)
1621 {
1622         TnyList *headers;
1623
1624         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1625         
1626         if (!header)
1627                 return;
1628
1629         headers = tny_simple_list_new ();
1630         tny_list_prepend (headers, G_OBJECT (header));
1631
1632         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1633
1634         g_object_unref (headers);
1635 }
1636
1637 static void
1638 set_active_account_from_tny_account (TnyAccount *account,
1639                                      ModestWindow *window)
1640 {
1641         const gchar *server_acc_name = tny_account_get_id (account);
1642         
1643         /* We need the TnyAccount provided by the
1644            account store because that is the one that
1645            knows the name of the Modest account */
1646         TnyAccount *modest_server_account = modest_server_account = 
1647                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1648                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1649                                                              server_acc_name);
1650         
1651         const gchar *modest_acc_name = 
1652                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1653         modest_window_set_active_account (window, modest_acc_name);
1654         g_object_unref (modest_server_account);
1655 }
1656
1657
1658 static void
1659 folder_refreshed_cb (ModestMailOperation *mail_op, 
1660                      TnyFolder *folder, 
1661                      gpointer user_data)
1662 {
1663         ModestMainWindow *win = NULL;
1664         GtkWidget *header_view;
1665
1666         g_return_if_fail (TNY_IS_FOLDER (folder));
1667
1668         win = MODEST_MAIN_WINDOW (user_data);
1669         header_view = 
1670                 modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
1671
1672         /* Check if folder is empty and set headers view contents style */
1673         if (tny_folder_get_all_count (folder) == 0) {
1674         printf ("DEBUG: %s: tny_folder_get_all_count() returned 0.\n", __FUNCTION__);
1675                 modest_main_window_set_contents_style (win,
1676                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1677         } else {
1678                 printf ("DEBUG: %s: tny_folder_get_all_count() returned >0.\n", __FUNCTION__);
1679         }
1680 }
1681
1682 void 
1683 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1684                                                TnyFolderStore *folder_store, 
1685                                                gboolean selected,
1686                                                ModestMainWindow *main_window)
1687 {
1688         ModestConf *conf;
1689         GtkWidget *header_view;
1690
1691         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1692
1693         header_view = modest_main_window_get_child_widget(main_window,
1694                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1695         if (!header_view)
1696                 return;
1697         
1698         conf = modest_runtime_get_conf ();
1699
1700         if (TNY_IS_ACCOUNT (folder_store)) {
1701                 if (selected) {
1702                         /* Update active account */
1703                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1704                         /* Show account details */
1705                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1706                 }
1707         } else {
1708                 if (TNY_IS_FOLDER (folder_store) && selected) {
1709                         
1710                         /* Update the active account */
1711                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1712                         if (account) {
1713                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1714                                 g_object_unref (account);
1715                                 account = NULL;
1716                         }
1717
1718                         /* Set the header style by default, it could
1719                            be changed later by the refresh callback to
1720                            empty */
1721                         modest_main_window_set_contents_style (main_window, 
1722                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1723
1724                         /* Set folder on header view. This function
1725                            will call tny_folder_refresh_async so we
1726                            pass a callback that will be called when
1727                            finished. We use that callback to set the
1728                            empty view if there are no messages */
1729                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1730                                                        TNY_FOLDER (folder_store),
1731                                                        folder_refreshed_cb,
1732                                                        main_window);
1733                         
1734                         /* Restore configuration. We need to do this
1735                            *after* the set_folder because the widget
1736                            memory asks the header view about its
1737                            folder  */
1738                         modest_widget_memory_restore (modest_runtime_get_conf (), 
1739                                                       G_OBJECT(header_view),
1740                                                       MODEST_CONF_HEADER_VIEW_KEY);
1741                 } else {
1742                         /* Update the active account */
1743                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1744                         /* Save only if we're seeing headers */
1745                         if (modest_main_window_get_contents_style (main_window) ==
1746                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1747                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
1748                                                            MODEST_CONF_HEADER_VIEW_KEY);
1749                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
1750                 }
1751         }
1752
1753         /* Update toolbar dimming state */
1754         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1755 }
1756
1757 void 
1758 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1759                                      ModestWindow *win)
1760 {
1761         GtkWidget *dialog;
1762         gchar *txt, *item;
1763         gboolean online;
1764
1765         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1766         
1767         online = tny_device_is_online (modest_runtime_get_device());
1768
1769         if (online) {
1770                 /* already online -- the item is simply not there... */
1771                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1772                                                  GTK_DIALOG_MODAL,
1773                                                  GTK_MESSAGE_WARNING,
1774                                                  GTK_BUTTONS_OK,
1775                                                  _("The %s you selected cannot be found"),
1776                                                  item);
1777                 gtk_dialog_run (GTK_DIALOG(dialog));
1778         } else {
1779                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1780                                                       GTK_WINDOW (win),
1781                                                       GTK_DIALOG_MODAL,
1782                                                       GTK_STOCK_CANCEL,
1783                                                       GTK_RESPONSE_REJECT,
1784                                                       GTK_STOCK_OK,
1785                                                       GTK_RESPONSE_ACCEPT,
1786                                                       NULL);
1787                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1788                                          "Do you want to get online?"), item);
1789                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1790                                     gtk_label_new (txt), FALSE, FALSE, 0);
1791                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1792                 g_free (txt);
1793
1794                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1795                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1796 //                      modest_platform_connect_and_wait ();
1797                 }
1798         }
1799         gtk_widget_destroy (dialog);
1800 }
1801
1802 void
1803 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1804                                      ModestWindow *win)
1805 {
1806         /* g_message ("%s %s", __FUNCTION__, link); */
1807 }       
1808
1809
1810 void
1811 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1812                                         ModestWindow *win)
1813 {
1814         modest_platform_activate_uri (link);
1815 }
1816
1817 void
1818 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1819                                           ModestWindow *win)
1820 {
1821         modest_platform_show_uri_popup (link);
1822 }
1823
1824 void
1825 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1826                                              ModestWindow *win)
1827 {
1828         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1829 }
1830
1831 void
1832 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1833                                           const gchar *address,
1834                                           ModestWindow *win)
1835 {
1836         /* g_message ("%s %s", __FUNCTION__, address); */
1837 }
1838
1839 void
1840 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1841 {
1842         TnyTransportAccount *transport_account;
1843         ModestMailOperation *mail_operation;
1844         MsgData *data;
1845         gchar *account_name, *from;
1846         ModestAccountMgr *account_mgr;
1847         gchar *info_text = NULL;
1848
1849         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1850         
1851         data = modest_msg_edit_window_get_msg_data (edit_window);
1852
1853         account_mgr = modest_runtime_get_account_mgr();
1854         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1855         if (!account_name) 
1856                 account_name = modest_account_mgr_get_default_account (account_mgr);
1857         if (!account_name) {
1858                 g_printerr ("modest: no account found\n");
1859                 modest_msg_edit_window_free_msg_data (edit_window, data);
1860                 return;
1861         }
1862
1863         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1864                 account_name = g_strdup (data->account_name);
1865         }
1866
1867         transport_account =
1868                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1869                                       (modest_runtime_get_account_store(),
1870                                        account_name,
1871                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1872         if (!transport_account) {
1873                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1874                 g_free (account_name);
1875                 modest_msg_edit_window_free_msg_data (edit_window, data);
1876                 return;
1877         }
1878         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1879
1880         /* Create the mail operation */         
1881         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1882         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1883
1884         modest_mail_operation_save_to_drafts (mail_operation,
1885                                               transport_account,
1886                                               data->draft_msg,
1887                                               edit_window,
1888                                               from,
1889                                               data->to, 
1890                                               data->cc, 
1891                                               data->bcc,
1892                                               data->subject, 
1893                                               data->plain_body, 
1894                                               data->html_body,
1895                                               data->attachments,
1896                                               data->priority_flags);
1897         /* Frees */
1898         g_free (from);
1899         g_free (account_name);
1900         g_object_unref (G_OBJECT (transport_account));
1901         g_object_unref (G_OBJECT (mail_operation));
1902
1903         modest_msg_edit_window_free_msg_data (edit_window, data);
1904
1905         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
1906         modest_platform_information_banner (NULL, NULL, info_text);
1907         g_free (info_text);
1908 }
1909
1910 /* For instance, when clicking the Send toolbar button when editing a message: */
1911 void
1912 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1913 {
1914         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1915
1916         if (!modest_msg_edit_window_check_names (edit_window))
1917                 return;
1918         
1919         /* Offer the connection dialog, if necessary: */        
1920         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window)))
1921                 return;
1922         
1923         /* FIXME: Code added just for testing. The final version will
1924            use the send queue provided by tinymail and some
1925            classifier */
1926         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
1927         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1928         if (!account_name) 
1929                 account_name = modest_account_mgr_get_default_account (account_mgr);
1930                 
1931         if (!account_name) {
1932                 g_printerr ("modest: no account found\n");
1933                 return;
1934         }
1935         
1936         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
1937
1938         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1939                 account_name = g_strdup (data->account_name);
1940         }
1941         
1942         /* Get the currently-active transport account for this modest account: */
1943         TnyTransportAccount *transport_account =
1944                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1945                                       (modest_runtime_get_account_store(),
1946                                        account_name));
1947         if (!transport_account) {
1948                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1949                 g_free (account_name);
1950                 modest_msg_edit_window_free_msg_data (edit_window, data);
1951                 return;
1952         }
1953         
1954         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
1955
1956         /* mail content checks and dialogs */
1957         if (data->subject == NULL || data->subject[0] == '\0') {
1958                 GtkResponseType response;
1959                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1960                                                                     _("mcen_nc_subject_is_empty_send"));
1961                 if (response == GTK_RESPONSE_CANCEL) {
1962                         g_free (account_name);
1963                         return;
1964                 }
1965         }
1966
1967         if (data->plain_body == NULL || data->plain_body[0] == '\0') {
1968                 GtkResponseType response;
1969                 gchar *note_message;
1970                 gchar *note_subject = data->subject;
1971                 if (note_subject == NULL || note_subject[0] == '\0')
1972                         note_subject = _("mail_va_no_subject");
1973                 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
1974                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1975                                                                     note_message);
1976                 g_free (note_message);
1977                 if (response == GTK_RESPONSE_CANCEL) {
1978                         g_free (account_name);
1979                         return;
1980                 }
1981         }
1982
1983         modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
1984
1985         /* Create the mail operation */
1986         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
1987         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1988
1989         modest_mail_operation_send_new_mail (mail_operation,
1990                                              transport_account,
1991                                              data->draft_msg,
1992                                              from,
1993                                              data->to, 
1994                                              data->cc, 
1995                                              data->bcc,
1996                                              data->subject, 
1997                                              data->plain_body, 
1998                                              data->html_body,
1999                                              data->attachments,
2000                                              data->priority_flags);
2001                                              
2002         /* Free data: */
2003         g_free (from);
2004         g_free (account_name);
2005         g_object_unref (G_OBJECT (transport_account));
2006         g_object_unref (G_OBJECT (mail_operation));
2007
2008         modest_msg_edit_window_free_msg_data (edit_window, data);
2009         modest_msg_edit_window_set_sent (edit_window, TRUE);
2010
2011         /* Save settings and close the window: */
2012         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2013 }
2014
2015 void 
2016 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2017                                   ModestMsgEditWindow *window)
2018 {
2019         ModestMsgEditFormatState *format_state = NULL;
2020
2021         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2022         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2023
2024         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2025                 return;
2026
2027         format_state = modest_msg_edit_window_get_format_state (window);
2028         g_return_if_fail (format_state != NULL);
2029
2030         format_state->bold = gtk_toggle_action_get_active (action);
2031         modest_msg_edit_window_set_format_state (window, format_state);
2032         g_free (format_state);
2033         
2034 }
2035
2036 void 
2037 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2038                                      ModestMsgEditWindow *window)
2039 {
2040         ModestMsgEditFormatState *format_state = NULL;
2041
2042         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2043         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2044
2045         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2046                 return;
2047
2048         format_state = modest_msg_edit_window_get_format_state (window);
2049         g_return_if_fail (format_state != NULL);
2050
2051         format_state->italics = gtk_toggle_action_get_active (action);
2052         modest_msg_edit_window_set_format_state (window, format_state);
2053         g_free (format_state);
2054         
2055 }
2056
2057 void 
2058 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2059                                      ModestMsgEditWindow *window)
2060 {
2061         ModestMsgEditFormatState *format_state = NULL;
2062
2063         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2064         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2065
2066         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2067                 return;
2068
2069         format_state = modest_msg_edit_window_get_format_state (window);
2070         g_return_if_fail (format_state != NULL);
2071
2072         format_state->bullet = gtk_toggle_action_get_active (action);
2073         modest_msg_edit_window_set_format_state (window, format_state);
2074         g_free (format_state);
2075         
2076 }
2077
2078 void 
2079 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2080                                      GtkRadioAction *selected,
2081                                      ModestMsgEditWindow *window)
2082 {
2083         ModestMsgEditFormatState *format_state = NULL;
2084         GtkJustification value;
2085
2086         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2087
2088         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2089                 return;
2090
2091         value = gtk_radio_action_get_current_value (selected);
2092
2093         format_state = modest_msg_edit_window_get_format_state (window);
2094         g_return_if_fail (format_state != NULL);
2095
2096         format_state->justification = value;
2097         modest_msg_edit_window_set_format_state (window, format_state);
2098         g_free (format_state);
2099 }
2100
2101 void 
2102 modest_ui_actions_on_select_editor_color (GtkAction *action,
2103                                           ModestMsgEditWindow *window)
2104 {
2105         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2106         g_return_if_fail (GTK_IS_ACTION (action));
2107
2108         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2109                 return;
2110
2111         modest_msg_edit_window_select_color (window);
2112 }
2113
2114 void 
2115 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2116                                                      ModestMsgEditWindow *window)
2117 {
2118         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2119         g_return_if_fail (GTK_IS_ACTION (action));
2120
2121         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2122                 return;
2123
2124         modest_msg_edit_window_select_background_color (window);
2125 }
2126
2127 void 
2128 modest_ui_actions_on_insert_image (GtkAction *action,
2129                                    ModestMsgEditWindow *window)
2130 {
2131         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2132         g_return_if_fail (GTK_IS_ACTION (action));
2133
2134         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2135                 return;
2136
2137         modest_msg_edit_window_insert_image (window);
2138 }
2139
2140 void 
2141 modest_ui_actions_on_attach_file (GtkAction *action,
2142                                   ModestMsgEditWindow *window)
2143 {
2144         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2145         g_return_if_fail (GTK_IS_ACTION (action));
2146
2147         modest_msg_edit_window_attach_file (window);
2148 }
2149
2150 void 
2151 modest_ui_actions_on_remove_attachments (GtkAction *action,
2152                                          ModestMsgEditWindow *window)
2153 {
2154         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2155         g_return_if_fail (GTK_IS_ACTION (action));
2156
2157         modest_msg_edit_window_remove_attachments (window, NULL);
2158 }
2159
2160 static void
2161 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2162                                             gpointer user_data)
2163 {
2164         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2165
2166         /* TODO: Note that folder creation might go wrong due to other
2167          * failures such as when the parent folder is non-writable. We can
2168          * query a GError* with modest_mail_operation_get_error(), but the
2169          * the error code (from tinymail) does not give us a clue about what
2170          * has gone wrong. We might use the error->message but it might come
2171          * from camel and not be suitable to show to the user directly. */
2172         modest_platform_information_banner (GTK_WIDGET (window), NULL,
2173                                             _CS("ckdg_ib_folder_already_exists"));
2174
2175 /*      modest_platform_information_banner (GTK_WIDGET (window), NULL,
2176                                             modest_mail_operation_get_error (mail_op)->message);*/
2177 }
2178
2179
2180 void 
2181 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2182 {
2183         TnyFolderStore *parent_folder;
2184         GtkWidget *folder_view;
2185         
2186         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2187
2188         folder_view = modest_main_window_get_child_widget (main_window,
2189                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2190         if (!folder_view)
2191                 return;
2192
2193         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2194         
2195         if (parent_folder) {
2196                 gboolean finished = FALSE;
2197                 gint result;
2198                 gchar *folder_name = NULL, *suggested_name = NULL;
2199
2200                 /* Run the new folder dialog */
2201                 while (!finished) {
2202                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
2203                                                                         parent_folder,
2204                                                                         suggested_name,
2205                                                                         &folder_name);
2206
2207                         g_free (suggested_name);
2208                         suggested_name = NULL;
2209
2210                         if (result == GTK_RESPONSE_REJECT) {
2211                                 finished = TRUE;
2212                         } else {
2213                                 ModestMailOperation *mail_op;
2214                                 TnyFolder *new_folder = NULL;
2215
2216                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2217                                                                                           G_OBJECT(main_window),
2218                                                                                           modest_ui_actions_new_folder_error_handler,
2219                                                                                           main_window);
2220
2221                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2222                                                                  mail_op);
2223                                 new_folder = modest_mail_operation_create_folder (mail_op,
2224                                                                                   parent_folder,
2225                                                                                   (const gchar *) folder_name);
2226                                 if (new_folder) {
2227                                         if (main_window) {
2228                                                 folder_view = modest_main_window_get_child_widget (main_window,
2229                                                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
2230                                                 if (folder_view)
2231                                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2232                                                                                           new_folder, TRUE);
2233                                         }
2234
2235                                         g_object_unref (new_folder);
2236                                         finished = TRUE;
2237                                 }
2238                                 g_object_unref (mail_op);
2239                         }
2240
2241                         suggested_name = folder_name;
2242                         folder_name = NULL;
2243                 }
2244
2245                 g_object_unref (parent_folder);
2246         }
2247 }
2248
2249 static void
2250 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2251                                                gpointer user_data)
2252 {
2253         GObject *win = modest_mail_operation_get_source (mail_op);
2254         const GError *error = NULL;
2255         const gchar *message = NULL;
2256         
2257         /* Get error message */
2258         error = modest_mail_operation_get_error (mail_op);
2259         if (error != NULL && error->message != NULL) {
2260                 message = error->message;
2261         } else {
2262                 message = _("!!! FIXME: Unable to rename");
2263         }
2264         
2265         /* Show notification dialog */
2266         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
2267         g_object_unref (win);
2268 }
2269
2270 void 
2271 modest_ui_actions_on_rename_folder (GtkAction *action,
2272                                      ModestMainWindow *main_window)
2273 {
2274         TnyFolderStore *folder;
2275         GtkWidget *folder_view;
2276         GtkWidget *header_view; 
2277
2278         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2279
2280         folder_view = modest_main_window_get_child_widget (main_window,
2281                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2282         if (!folder_view)
2283                 return;
2284
2285         header_view = modest_main_window_get_child_widget (main_window,
2286                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2287         
2288         if (!header_view)
2289                 return;
2290
2291         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2292         if (!folder)
2293                 return;
2294
2295         /* Offer the connection dialog if necessary: */
2296         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2297                 g_object_unref (G_OBJECT (folder));
2298                 return;
2299         }
2300
2301         
2302         if (TNY_IS_FOLDER (folder)) {
2303                 gchar *folder_name;
2304                 gint response;
2305                 const gchar *current_name;
2306
2307                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2308                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), NULL,
2309                                                                      current_name, &folder_name);
2310
2311                 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2312                         ModestMailOperation *mail_op;
2313
2314                         mail_op = 
2315                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO, 
2316                                                                                G_OBJECT(main_window),
2317                                                                                modest_ui_actions_rename_folder_error_handler,
2318                                                                                NULL);
2319
2320
2321                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2322                                                          mail_op);
2323
2324                         modest_header_view_clear (MODEST_HEADER_VIEW (header_view));
2325                         
2326                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2327                                                           TNY_FOLDER(folder), TRUE);
2328
2329
2330                         modest_header_view_clear ((ModestHeaderView *) header_view);
2331  
2332                         modest_mail_operation_rename_folder (mail_op,
2333                                                              TNY_FOLDER (folder),
2334                                                              (const gchar *) folder_name);
2335
2336                         g_object_unref (mail_op);
2337                         g_free (folder_name);
2338                 }
2339         }
2340         g_object_unref (folder);
2341 }
2342
2343 static void
2344 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2345                                                gpointer user_data)
2346 {
2347         GObject *win = modest_mail_operation_get_source (mail_op);
2348
2349         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2350                                                 _("mail_in_ui_folder_delete_error"));
2351         g_object_unref (win);
2352 }
2353
2354 static void
2355 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2356 {
2357         TnyFolderStore *folder;
2358         GtkWidget *folder_view;
2359         gint response;
2360         gchar *message;
2361         
2362         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2363
2364         folder_view = modest_main_window_get_child_widget (main_window,
2365                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2366         if (!folder_view)
2367                 return;
2368
2369         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2370
2371         /* Show an error if it's an account */
2372         if (!TNY_IS_FOLDER (folder)) {
2373                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2374                                                         _("mail_in_ui_folder_delete_error"));
2375                 g_object_unref (G_OBJECT (folder));
2376                 return ;
2377         }
2378
2379         /* Offer the connection dialog if necessary: */
2380         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2381                 g_object_unref (G_OBJECT (folder));
2382                 return;
2383         }
2384
2385         /* Ask the user */      
2386         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2387                                     tny_folder_get_name (TNY_FOLDER (folder)));
2388         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2389                                                             (const gchar *) message);
2390         g_free (message);
2391
2392         if (response == GTK_RESPONSE_OK) {
2393                 ModestMailOperation *mail_op = 
2394                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2395                                                                        G_OBJECT(main_window),
2396                                                                        modest_ui_actions_delete_folder_error_handler,
2397                                                                        NULL);
2398
2399                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2400                                                  mail_op);
2401                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2402                 g_object_unref (G_OBJECT (mail_op));
2403         }
2404
2405         g_object_unref (G_OBJECT (folder));
2406 }
2407
2408 void 
2409 modest_ui_actions_on_delete_folder (GtkAction *action,
2410                                      ModestMainWindow *main_window)
2411 {
2412         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2413
2414         delete_folder (main_window, FALSE);
2415 }
2416
2417 void 
2418 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2419 {
2420         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2421         
2422         delete_folder (main_window, TRUE);
2423 }
2424
2425 void
2426 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2427                                          const gchar* server_account_name,
2428                                          gchar **username,
2429                                          gchar **password, 
2430                                          gboolean *cancel, 
2431                                          gboolean *remember,
2432                                          ModestMainWindow *main_window)
2433 {
2434         g_return_if_fail(server_account_name);
2435         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2436         
2437         /* Initalize output parameters: */
2438         if (cancel)
2439                 *cancel = FALSE;
2440                 
2441         if (remember)
2442                 *remember = TRUE;
2443                 
2444 #ifdef MODEST_PLATFORM_MAEMO
2445         /* Maemo uses a different (awkward) button order,
2446          * It should probably just use gtk_alternative_dialog_button_order ().
2447          */
2448         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2449                                               NULL,
2450                                               GTK_DIALOG_MODAL,
2451                                               GTK_STOCK_OK,
2452                                               GTK_RESPONSE_ACCEPT,
2453                                               GTK_STOCK_CANCEL,
2454                                               GTK_RESPONSE_REJECT,
2455                                               NULL);
2456 #else
2457         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2458                                               NULL,
2459                                               GTK_DIALOG_MODAL,
2460                                               GTK_STOCK_CANCEL,
2461                                               GTK_RESPONSE_REJECT,
2462                                               GTK_STOCK_OK,
2463                                               GTK_RESPONSE_ACCEPT,
2464                                               NULL);
2465 #endif /* MODEST_PLATFORM_MAEMO */
2466
2467         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2468         
2469         gchar *server_name = modest_server_account_get_hostname (
2470                 modest_runtime_get_account_mgr(), server_account_name);
2471         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2472                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2473                 *cancel = TRUE;
2474                 return;
2475         }
2476         
2477         /* This causes a warning because the logical ID has no %s in it, 
2478          * though the translation does, but there is not much we can do about that: */
2479         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2480         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2481                             FALSE, FALSE, 0);
2482         g_free (txt);
2483         g_free (server_name);
2484         server_name = NULL;
2485
2486         /* username: */
2487         gchar *initial_username = modest_server_account_get_username (
2488                 modest_runtime_get_account_mgr(), server_account_name);
2489         
2490         GtkWidget *entry_username = gtk_entry_new ();
2491         if (initial_username)
2492                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2493         /* Dim this if a connection has ever succeeded with this username,
2494          * as per the UI spec: */
2495         const gboolean username_known = 
2496                 modest_server_account_get_username_has_succeeded(
2497                         modest_runtime_get_account_mgr(), server_account_name);
2498         gtk_widget_set_sensitive (entry_username, !username_known);
2499         
2500 #ifdef MODEST_PLATFORM_MAEMO
2501         /* Auto-capitalization is the default, so let's turn it off: */
2502         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2503         
2504         /* Create a size group to be used by all captions.
2505          * Note that HildonCaption does not create a default size group if we do not specify one.
2506          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2507         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2508         
2509         GtkWidget *caption = hildon_caption_new (sizegroup, 
2510                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2511         gtk_widget_show (entry_username);
2512         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2513                 FALSE, FALSE, MODEST_MARGIN_HALF);
2514         gtk_widget_show (caption);
2515 #else 
2516         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2517                             TRUE, FALSE, 0);
2518 #endif /* MODEST_PLATFORM_MAEMO */      
2519                             
2520         /* password: */
2521         GtkWidget *entry_password = gtk_entry_new ();
2522         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2523         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2524         
2525 #ifdef MODEST_PLATFORM_MAEMO
2526         /* Auto-capitalization is the default, so let's turn it off: */
2527         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2528                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2529         
2530         caption = hildon_caption_new (sizegroup, 
2531                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2532         gtk_widget_show (entry_password);
2533         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2534                 FALSE, FALSE, MODEST_MARGIN_HALF);
2535         gtk_widget_show (caption);
2536         g_object_unref (sizegroup);
2537 #else 
2538         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2539                             TRUE, FALSE, 0);
2540 #endif /* MODEST_PLATFORM_MAEMO */      
2541                                 
2542 /* This is not in the Maemo UI spec:
2543         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2544         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2545                             TRUE, FALSE, 0);
2546 */
2547
2548         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2549         
2550         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2551                 if (username) {
2552                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2553                         
2554                         modest_server_account_set_username (
2555                                  modest_runtime_get_account_mgr(), server_account_name, 
2556                                  *username);
2557                                  
2558                         const gboolean username_was_changed = 
2559                                 (strcmp (*username, initial_username) != 0);
2560                         if (username_was_changed) {
2561                                 g_warning ("%s: tinymail does not yet support changing the "
2562                                         "username in the get_password() callback.\n", __FUNCTION__);
2563                         }
2564                 }
2565                         
2566                 if (password) {
2567                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2568                         
2569                         /* We do not save the password in the configuration, 
2570                          * because this function is only called for passwords that should 
2571                          * not be remembered:
2572                         modest_server_account_set_password (
2573                                  modest_runtime_get_account_mgr(), server_account_name, 
2574                                  *password);
2575                         */
2576                 }
2577                 
2578                 if (cancel)
2579                         *cancel   = FALSE;
2580                         
2581         } else {
2582                 if (username)
2583                         *username = NULL;
2584                         
2585                 if (password)
2586                         *password = NULL;
2587                         
2588                 if (cancel)
2589                         *cancel   = TRUE;
2590         }
2591
2592 /* This is not in the Maemo UI spec:
2593         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2594                 *remember = TRUE;
2595         else
2596                 *remember = FALSE;
2597 */
2598
2599         gtk_widget_destroy (dialog);
2600         
2601         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2602 }
2603
2604 void
2605 modest_ui_actions_on_cut (GtkAction *action,
2606                           ModestWindow *window)
2607 {
2608         GtkWidget *focused_widget;
2609
2610         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2611         if (GTK_IS_EDITABLE (focused_widget)) {
2612                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2613         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2614                 GtkTextBuffer *buffer;
2615                 GtkClipboard *clipboard;
2616
2617                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2618                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2619                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2620                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2621         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2622                 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2623         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2624                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2625         }
2626 }
2627
2628 void
2629 modest_ui_actions_on_copy (GtkAction *action,
2630                            ModestWindow *window)
2631 {
2632         GtkClipboard *clipboard;
2633         GtkWidget *focused_widget;
2634
2635         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2636         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2637
2638         if (GTK_IS_LABEL (focused_widget)) {
2639                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2640         } else if (GTK_IS_EDITABLE (focused_widget)) {
2641                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2642         } else if (GTK_IS_HTML (focused_widget)) {
2643                 gtk_html_copy (GTK_HTML (focused_widget));
2644         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2645                 GtkTextBuffer *buffer;
2646                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2647                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2648                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2649         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2650                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2651                 TnyIterator *iter = tny_list_create_iterator (header_list);
2652                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2653                 TnyFolder *folder = tny_header_get_folder (header);
2654                 TnyAccount *account = tny_folder_get_account (folder);
2655                 const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2656                 /* If it's POP then ask */
2657                 gboolean ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2658                        MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2659                 g_object_unref (account);
2660                 g_object_unref (folder);
2661                 g_object_unref (header);
2662                 g_object_unref (iter);
2663                 
2664                 /* Check that the messages have been previously downloaded */
2665                 gboolean continue_download = TRUE;
2666                 if (ask)
2667                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window), FALSE);
2668                 if (continue_download)
2669                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2670                 g_object_unref (header_list);
2671         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2672                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2673         }    
2674
2675         /* Show information banner */
2676         modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2677         
2678 }
2679
2680 void
2681 modest_ui_actions_on_undo (GtkAction *action,
2682                            ModestWindow *window)
2683 {
2684         ModestEmailClipboard *clipboard = NULL;
2685
2686         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2687                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2688         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2689                 /* Clear clipboard source */
2690                 clipboard = modest_runtime_get_email_clipboard ();
2691                 modest_email_clipboard_clear (clipboard);               
2692         }
2693         else {
2694                 g_return_if_reached ();
2695         }
2696 }
2697
2698 void
2699 modest_ui_actions_on_redo (GtkAction *action,
2700                            ModestWindow *window)
2701 {
2702         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2703                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2704         }
2705         else {
2706                 g_return_if_reached ();
2707         }
2708 }
2709
2710
2711 static void
2712 paste_msgs_cb (const GObject *object, gpointer user_data)
2713 {
2714         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2715         g_return_if_fail (GTK_IS_WIDGET (user_data));
2716         
2717         /* destroy information note */
2718         gtk_widget_destroy (GTK_WIDGET(user_data));
2719 }
2720
2721 void
2722 modest_ui_actions_on_paste (GtkAction *action,
2723                             ModestWindow *window)
2724 {
2725         GtkWidget *focused_widget = NULL;
2726         GtkWidget *inf_note = NULL;
2727         ModestMailOperation *mail_op = NULL;
2728
2729         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2730         if (GTK_IS_EDITABLE (focused_widget)) {
2731                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2732         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2733                 GtkTextBuffer *buffer;
2734                 GtkClipboard *clipboard;
2735
2736                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2737                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2738                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2739         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2740                 ModestEmailClipboard *clipboard = NULL;
2741                 TnyFolder *src_folder = NULL;
2742                 TnyFolderStore *folder_store = NULL;
2743                 TnyList *data = NULL;           
2744                 gboolean delete = FALSE;
2745                 
2746                 /* Check clipboard source */
2747                 clipboard = modest_runtime_get_email_clipboard ();
2748                 if (modest_email_clipboard_cleared (clipboard)) 
2749                         return;
2750                 
2751                 /* Get elements to paste */
2752                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
2753
2754                 /* Create a new mail operation */
2755                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
2756                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2757                                                  mail_op);
2758                 
2759                 /* Get destination folder */
2760                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
2761
2762                 /* Launch notification */
2763                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
2764                                                              _CS("ckct_nw_pasting"));
2765                 if (inf_note != NULL)  {
2766                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
2767                         gtk_widget_show (GTK_WIDGET(inf_note));
2768                 }
2769
2770                 /* transfer messages  */
2771                 if (data != NULL) {
2772                         modest_mail_operation_xfer_msgs (mail_op, 
2773                                                          data,
2774                                                          TNY_FOLDER (folder_store),
2775                                                          delete,
2776                                                          paste_msgs_cb,
2777                                                          inf_note);
2778                         
2779                 } else if (src_folder != NULL) {                        
2780                         modest_mail_operation_xfer_folder (mail_op, 
2781                                                            src_folder,
2782                                                            folder_store,
2783                                                            delete,
2784                                                            paste_msgs_cb,
2785                                                            inf_note);
2786                 }
2787
2788                 /* Free */
2789                 if (data != NULL) 
2790                         g_object_unref (data);
2791                 if (src_folder != NULL) 
2792                         g_object_unref (src_folder);
2793                 if (folder_store != NULL) 
2794                         g_object_unref (folder_store);
2795         }
2796 }
2797
2798
2799 void
2800 modest_ui_actions_on_select_all (GtkAction *action,
2801                                  ModestWindow *window)
2802 {
2803         GtkWidget *focused_widget;
2804
2805         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2806         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2807                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2808         } else if (GTK_IS_LABEL (focused_widget)) {
2809                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2810         } else if (GTK_IS_EDITABLE (focused_widget)) {
2811                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2812         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2813                 GtkTextBuffer *buffer;
2814                 GtkTextIter start, end;
2815
2816                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2817                 gtk_text_buffer_get_start_iter (buffer, &start);
2818                 gtk_text_buffer_get_end_iter (buffer, &end);
2819                 gtk_text_buffer_select_range (buffer, &start, &end);
2820         } else if (GTK_IS_HTML (focused_widget)) {
2821                 gtk_html_select_all (GTK_HTML (focused_widget));
2822         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2823                 GtkWidget *header_view = focused_widget;
2824                 GtkTreeSelection *selection = NULL;
2825                 
2826                 if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
2827                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2828                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2829                                 
2830                 /* Select all messages */
2831                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2832                 gtk_tree_selection_select_all (selection);
2833
2834                 /* Set focuse on header view */
2835                 gtk_widget_grab_focus (header_view);
2836         }
2837
2838 }
2839
2840 void
2841 modest_ui_actions_on_mark_as_read (GtkAction *action,
2842                                    ModestWindow *window)
2843 {       
2844         g_return_if_fail (MODEST_IS_WINDOW(window));
2845                 
2846         /* Mark each header as read */
2847         do_headers_action (window, headers_action_mark_as_read, NULL);
2848 }
2849
2850 void
2851 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2852                                      ModestWindow *window)
2853 {       
2854         g_return_if_fail (MODEST_IS_WINDOW(window));
2855                 
2856         /* Mark each header as read */
2857         do_headers_action (window, headers_action_mark_as_unread, NULL);
2858 }
2859
2860 void
2861 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2862                                   GtkRadioAction *selected,
2863                                   ModestWindow *window)
2864 {
2865         gint value;
2866
2867         value = gtk_radio_action_get_current_value (selected);
2868         if (MODEST_IS_WINDOW (window)) {
2869                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2870         }
2871 }
2872
2873 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2874                                                         GtkRadioAction *selected,
2875                                                         ModestWindow *window)
2876 {
2877         TnyHeaderFlags flags;
2878         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2879
2880         flags = gtk_radio_action_get_current_value (selected);
2881         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2882 }
2883
2884 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2885                                                            GtkRadioAction *selected,
2886                                                            ModestWindow *window)
2887 {
2888         gint file_format;
2889
2890         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2891
2892         file_format = gtk_radio_action_get_current_value (selected);
2893         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2894 }
2895
2896
2897 void     
2898 modest_ui_actions_on_zoom_plus (GtkAction *action,
2899                                 ModestWindow *window)
2900 {
2901         g_return_if_fail (MODEST_IS_WINDOW (window));
2902
2903         modest_window_zoom_plus (MODEST_WINDOW (window));
2904 }
2905
2906 void     
2907 modest_ui_actions_on_zoom_minus (GtkAction *action,
2908                                  ModestWindow *window)
2909 {
2910         g_return_if_fail (MODEST_IS_WINDOW (window));
2911
2912         modest_window_zoom_minus (MODEST_WINDOW (window));
2913 }
2914
2915 void     
2916 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2917                                            ModestWindow *window)
2918 {
2919         ModestWindowMgr *mgr;
2920         gboolean fullscreen, active;
2921         g_return_if_fail (MODEST_IS_WINDOW (window));
2922
2923         mgr = modest_runtime_get_window_mgr ();
2924
2925         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2926         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2927
2928         if (active != fullscreen) {
2929                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2930                 gtk_window_present (GTK_WINDOW (window));
2931         }
2932 }
2933
2934 void
2935 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2936                                         ModestWindow *window)
2937 {
2938         ModestWindowMgr *mgr;
2939         gboolean fullscreen;
2940
2941         g_return_if_fail (MODEST_IS_WINDOW (window));
2942
2943         mgr = modest_runtime_get_window_mgr ();
2944         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2945         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2946
2947         gtk_window_present (GTK_WINDOW (window));
2948 }
2949
2950 /* 
2951  * Used by modest_ui_actions_on_details to call do_headers_action 
2952  */
2953 static void
2954 headers_action_show_details (TnyHeader *header, 
2955                              ModestWindow *window,
2956                              gpointer user_data)
2957
2958 {
2959         GtkWidget *dialog;
2960         
2961         /* Create dialog */
2962         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2963
2964         /* Run dialog */
2965         gtk_widget_show_all (dialog);
2966         gtk_dialog_run (GTK_DIALOG (dialog));
2967
2968         gtk_widget_destroy (dialog);
2969 }
2970
2971 /*
2972  * Show the folder details in a ModestDetailsDialog widget
2973  */
2974 static void
2975 show_folder_details (TnyFolder *folder, 
2976                      GtkWindow *window)
2977 {
2978         GtkWidget *dialog;
2979         
2980         /* Create dialog */
2981         dialog = modest_details_dialog_new_with_folder (window, folder);
2982
2983         /* Run dialog */
2984         gtk_widget_show_all (dialog);
2985         gtk_dialog_run (GTK_DIALOG (dialog));
2986
2987         gtk_widget_destroy (dialog);
2988 }
2989
2990 /*
2991  * Show the header details in a ModestDetailsDialog widget
2992  */
2993 void     
2994 modest_ui_actions_on_details (GtkAction *action, 
2995                               ModestWindow *win)
2996 {
2997         TnyList * headers_list;
2998         TnyIterator *iter;
2999         TnyHeader *header;              
3000
3001         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3002                 TnyMsg *msg;
3003
3004                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3005                 if (!msg)
3006                         return;
3007                 g_object_unref (msg);           
3008
3009                 headers_list = get_selected_headers (win);
3010                 if (!headers_list)
3011                         return;
3012
3013                 iter = tny_list_create_iterator (headers_list);
3014
3015                 header = TNY_HEADER (tny_iterator_get_current (iter));
3016                 headers_action_show_details (header, win, NULL);
3017                 g_object_unref (header);
3018
3019                 g_object_unref (iter);
3020                 g_object_unref (headers_list);
3021
3022         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3023                 GtkWidget *folder_view, *header_view;
3024
3025                 /* Check which widget has the focus */
3026                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3027                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
3028                 if (gtk_widget_is_focus (folder_view)) {
3029                         TnyFolderStore *folder_store
3030                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3031                         if (!folder_store) {
3032                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3033                                 return; 
3034                         }
3035                         /* Show only when it's a folder */
3036                         /* This function should not be called for account items, 
3037                          * because we dim the menu item for them. */
3038                         if (TNY_IS_FOLDER (folder_store)) {
3039                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3040                         }
3041
3042                         g_object_unref (folder_store);
3043
3044                 } else {
3045                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3046                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3047                         /* Show details of each header */
3048                         do_headers_action (win, headers_action_show_details, header_view);
3049                 }
3050         }
3051 }
3052
3053 void     
3054 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3055                                      ModestMsgEditWindow *window)
3056 {
3057         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3058
3059         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3060 }
3061
3062 void     
3063 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3064                                       ModestMsgEditWindow *window)
3065 {
3066         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3067
3068         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3069 }
3070
3071 void
3072 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3073                                        ModestMainWindow *main_window)
3074 {
3075         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3076
3077         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3078                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3079         else
3080                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3081 }
3082
3083 void 
3084 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3085                                      ModestWindow *window)
3086 {
3087         gboolean active, fullscreen = FALSE;
3088         ModestWindowMgr *mgr;
3089
3090         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3091
3092         /* Check if we want to toggle the toolbar vuew in fullscreen
3093            or normal mode */
3094         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3095                      "ViewShowToolbarFullScreen")) {
3096                 fullscreen = TRUE;
3097         }
3098
3099         /* Toggle toolbar */
3100         mgr = modest_runtime_get_window_mgr ();
3101         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
3102 }
3103
3104 void     
3105 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3106                                            ModestMsgEditWindow *window)
3107 {
3108         modest_msg_edit_window_select_font (window);
3109 }
3110
3111 void
3112 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3113                                                   const gchar *display_name,
3114                                                   GtkWindow *window)
3115 {
3116         /* Do not change the application name if the widget has not
3117            the focus. This callback could be called even if the folder
3118            view has not the focus, because the handled signal could be
3119            emitted when the folder view is redrawn */
3120         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3121                 if (display_name)
3122                         gtk_window_set_title (window, display_name);
3123                 else
3124                         gtk_window_set_title (window, " ");
3125         }
3126 }
3127
3128 void
3129 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3130 {
3131         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3132         modest_msg_edit_window_select_contacts (window);
3133 }
3134
3135 void
3136 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3137 {
3138         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3139         modest_msg_edit_window_check_names (window);
3140 }
3141
3142
3143 static GtkWidget*
3144 create_move_to_dialog (GtkWindow *win,
3145                        GtkWidget *folder_view,
3146                        GtkWidget **tree_view)
3147 {
3148         GtkWidget *dialog, *scroll;
3149
3150         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3151                                               GTK_WINDOW (win),
3152                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3153                                               GTK_STOCK_OK,
3154                                               GTK_RESPONSE_ACCEPT,
3155                                               GTK_STOCK_CANCEL,
3156                                               GTK_RESPONSE_REJECT,
3157                                               NULL);
3158
3159         /* Create scrolled window */
3160         scroll = gtk_scrolled_window_new (NULL, NULL);
3161         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3162                                          GTK_POLICY_AUTOMATIC,
3163                                          GTK_POLICY_AUTOMATIC);
3164
3165         /* Create folder view */
3166         *tree_view = modest_platform_create_folder_view (NULL);
3167
3168         /* It could happen that we're trying to move a message from a
3169            window (msg window for example) after the main window was
3170            closed, so we can not just get the model of the folder
3171            view */
3172         if (MODEST_IS_FOLDER_VIEW (folder_view))
3173                 gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
3174                                          gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
3175         else
3176                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3177                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3178
3179         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3180         
3181         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3182
3183         /* Add scroll to dialog */
3184         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3185                             scroll, FALSE, FALSE, 0);
3186
3187         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3188
3189         return dialog;
3190 }
3191
3192 /*
3193  * Returns TRUE if at least one of the headers of the list belongs to
3194  * a message that has been fully retrieved.
3195  */
3196 static gboolean
3197 has_retrieved_msgs (TnyList *list)
3198 {
3199         TnyIterator *iter;
3200         gboolean found = FALSE;
3201
3202         iter = tny_list_create_iterator (list);
3203         while (tny_iterator_is_done (iter) && !found) {
3204                 TnyHeader *header;
3205                 TnyHeaderFlags flags;
3206
3207                 header = TNY_HEADER (tny_iterator_get_current (iter));
3208                 flags = tny_header_get_flags (header);
3209                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
3210                         found = TRUE;
3211
3212                 if (!found)
3213                         tny_iterator_next (iter);
3214         }
3215         g_object_unref (iter);
3216
3217         return found;
3218 }
3219
3220 /*
3221  * Shows a confirmation dialog to the user when we're moving messages
3222  * from a remote server to the local storage. Returns the dialog
3223  * response. If it's other kind of movement the it always returns
3224  * GTK_RESPONSE_OK
3225  */
3226 static gint
3227 msgs_move_to_confirmation (GtkWindow *win,
3228                            TnyFolder *dest_folder,
3229                            TnyList *headers)
3230 {
3231         gint response = GTK_RESPONSE_OK;
3232
3233         /* If the destination is a local folder */
3234         if (modest_tny_folder_is_local_folder (dest_folder)) {
3235                 TnyFolder *src_folder;
3236                 TnyIterator *iter;
3237                 TnyHeader *header;
3238
3239                 /* Get source folder */
3240                 iter = tny_list_create_iterator (headers);
3241                 header = TNY_HEADER (tny_iterator_get_current (iter));
3242                 src_folder = tny_header_get_folder (header);
3243                 g_object_unref (header);
3244                 g_object_unref (iter);
3245
3246                 /* if no src_folder, message may be an attahcment */
3247                 if (src_folder == NULL) 
3248                         return GTK_RESPONSE_CANCEL;
3249
3250                 /* If the source is a remote folder */
3251                 if (!modest_tny_folder_is_local_folder (src_folder)) {
3252                         const gchar *message;
3253                         
3254                         if (has_retrieved_msgs (headers))
3255                                 message = ngettext ("mcen_nc_move_retrieve", "mcen_nc_move_retrieves",
3256                                                     tny_list_get_length (headers));
3257                         else 
3258                                 message = ngettext ("mcen_nc_move_header", "mcen_nc_move_headers",
3259                                                     tny_list_get_length (headers));
3260
3261                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
3262                                                                             (const gchar *) message);
3263                 }
3264                 g_object_unref (src_folder);
3265         }
3266         return response;
3267 }
3268
3269
3270
3271 static void
3272 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3273 {
3274         ModestMsgViewWindow *self = NULL;
3275
3276         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3277         self = MODEST_MSG_VIEW_WINDOW (object);
3278         
3279         if (!modest_msg_view_window_select_next_message (self))
3280                 if (!modest_msg_view_window_select_previous_message (self))
3281                         /* No more messages to view, so close this window */
3282                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3283 }
3284
3285 void
3286 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3287                                              gpointer user_data)
3288 {
3289         GObject *win = modest_mail_operation_get_source (mail_op);
3290         const GError *error = NULL;
3291         const gchar *message = NULL;
3292         
3293         /* Get error message */
3294         error = modest_mail_operation_get_error (mail_op);
3295         if (error != NULL && error->message != NULL) {
3296                 message = error->message;
3297         } else {
3298                 message = _("mail_in_ui_folder_move_target_error");
3299         }
3300         
3301         /* Show notification dialog */
3302         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3303         g_object_unref (win);
3304 }
3305
3306 void
3307 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3308                                               gpointer user_data)
3309 {
3310         GObject *win = modest_mail_operation_get_source (mail_op);
3311         const GError *error = modest_mail_operation_get_error (mail_op);
3312
3313         g_return_if_fail (error != NULL);
3314         if (error->message != NULL)             
3315                 g_printerr ("modest: %s\n", error->message);
3316         else
3317                 g_printerr ("modest: unkonw error on send&receive operation");
3318
3319         /* Show error message */
3320 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3321 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3322 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3323 /*      else  */
3324 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3325 /*                                                      _CS("sfil_ib_unable_to_send")); */
3326         g_object_unref (win);
3327 }
3328
3329 static void
3330 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3331                        TnyHeader *header, 
3332                        TnyMsg *msg, 
3333                        gpointer user_data)
3334 {
3335         TnyList *parts;
3336         TnyIterator *iter;
3337         gint pending_purges = 0;
3338         gboolean some_purged = FALSE;
3339         ModestWindow *win = MODEST_WINDOW (user_data);
3340
3341         /* If there was any error */
3342         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
3343                 return;
3344
3345         /* Once the message has been retrieved for purging, we check if
3346          * it's all ok for purging */
3347
3348         parts = tny_simple_list_new ();
3349         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3350         iter = tny_list_create_iterator (parts);
3351
3352         while (!tny_iterator_is_done (iter)) {
3353                 TnyMimePart *part;
3354                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3355                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)) {
3356                         if (tny_mime_part_is_purged (part))
3357                                 some_purged = TRUE;
3358                         else
3359                                 pending_purges++;
3360                 }
3361                 tny_iterator_next (iter);
3362         }
3363
3364         if (pending_purges>0) {
3365                 gint response;
3366                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3367
3368                 if (response == GTK_RESPONSE_OK) {
3369                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3370                         tny_iterator_first (iter);
3371                         while (!tny_iterator_is_done (iter)) {
3372                                 TnyMimePart *part;
3373                                 
3374                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3375                                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))
3376                                         tny_mime_part_set_purged (part);
3377                                 tny_iterator_next (iter);
3378                         }
3379                         
3380                         tny_msg_rewrite_cache (msg);
3381                 }
3382         } else {
3383                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3384         }
3385
3386         /* remove attachments */
3387         tny_iterator_first (iter);
3388         while (!tny_iterator_is_done (iter)) {
3389                 TnyMimePart *part;
3390                         
3391                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3392                 g_object_unref (part);
3393                 tny_iterator_next (iter);
3394         }
3395
3396         g_object_unref (iter);
3397         g_object_unref (parts);
3398 }
3399
3400 static void
3401 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3402                                                      ModestMainWindow *win)
3403 {
3404         GtkWidget *header_view;
3405         TnyList *header_list;
3406         TnyIterator *iter;
3407         TnyHeader *header;
3408         TnyHeaderFlags flags;
3409         ModestWindow *msg_view_window =  NULL;
3410         gboolean found;
3411
3412         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3413
3414         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3415                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3416
3417         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3418
3419         if (tny_list_get_length (header_list) == 1) {
3420                 iter = tny_list_create_iterator (header_list);
3421                 header = TNY_HEADER (tny_iterator_get_current (iter));
3422                 g_object_unref (iter);
3423         } else {
3424                 return;
3425         }
3426
3427         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3428                                                           header, &msg_view_window);
3429         flags = tny_header_get_flags (header);
3430         if (!(flags & TNY_HEADER_FLAG_CACHED))
3431                 return;
3432         if (found) {
3433                 if (msg_view_window != NULL) 
3434                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3435                 else {
3436                         /* do nothing; uid was registered before, so window is probably on it's way */
3437                         g_warning ("debug: header %p has already been registered", header);
3438                 }
3439         } else {
3440                 ModestMailOperation *mail_op = NULL;
3441                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3442                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3443                                                                          G_OBJECT (win),
3444                                                                          modest_ui_actions_get_msgs_full_error_handler,
3445                                                                          NULL);
3446                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3447                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3448                 
3449                 g_object_unref (mail_op);
3450         }
3451         if (header)
3452                 g_object_unref (header);
3453         if (header_list)
3454                 g_object_unref (header_list);
3455 }
3456
3457 /**
3458  * Utility function that transfer messages from both the main window
3459  * and the msg view window when using the "Move to" dialog
3460  */
3461 static void
3462 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
3463                                               ModestWindow *win)
3464 {
3465         TnyList *headers = NULL;
3466         gint response = 0;
3467
3468         if (!TNY_IS_FOLDER (dst_folder)) {
3469                 modest_platform_information_banner (GTK_WIDGET (win),
3470                                                     NULL,
3471                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
3472                 return;
3473         }
3474
3475         /* Get selected headers */
3476         headers = get_selected_headers (MODEST_WINDOW (win));
3477
3478         /* Ask for user confirmation */
3479         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3480                                               TNY_FOLDER (dst_folder), 
3481                                               headers);
3482
3483         /* Transfer messages */
3484         if (response == GTK_RESPONSE_OK) {
3485                 ModestMailOperation *mail_op = 
3486                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3487                                                                        G_OBJECT(win),
3488                                                                        modest_ui_actions_move_folder_error_handler,
3489                                                                        NULL);
3490                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3491                                                  mail_op);
3492
3493                 modest_mail_operation_xfer_msgs (mail_op, 
3494                                                  headers,
3495                                                  TNY_FOLDER (dst_folder),
3496                                                  TRUE,
3497                                                  (MODEST_IS_MSG_VIEW_WINDOW (win)) ? transfer_msgs_from_viewer_cb : NULL,
3498                                                  NULL);
3499
3500                 g_object_unref (G_OBJECT (mail_op));
3501         }
3502         g_object_unref (headers);
3503 }
3504
3505
3506 /*
3507  * UI handler for the "Move to" action when invoked from the
3508  * ModestMainWindow
3509  */
3510 static void 
3511 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
3512                                           GtkWidget *folder_view,
3513                                           TnyFolderStore *dst_folder,
3514                                           ModestMainWindow *win)
3515 {
3516         GtkWidget *header_view = NULL;
3517         ModestMailOperation *mail_op = NULL;
3518         TnyFolderStore *src_folder;
3519
3520         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3521
3522         /* Get the source folder */
3523         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3524         
3525         /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
3526         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
3527                                                                       src_folder))
3528                 goto end;
3529
3530         /* Get header view */
3531         header_view = 
3532                 modest_main_window_get_child_widget (win, MODEST_WIDGET_TYPE_HEADER_VIEW);
3533
3534         /* Get folder or messages to transfer */
3535         if (gtk_widget_is_focus (folder_view)) {
3536
3537                 /* Allow only to transfer folders to the local root folder */
3538                 if (TNY_IS_ACCOUNT (dst_folder) && 
3539                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder))
3540                         goto end;
3541                 
3542                 /* Clean folder on header view before moving it */
3543                 modest_header_view_clear (MODEST_HEADER_VIEW (header_view)); 
3544
3545                 if (TNY_IS_FOLDER (src_folder)) {
3546                         mail_op = 
3547                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3548                                                                                G_OBJECT(win),
3549                                                                                modest_ui_actions_move_folder_error_handler,
3550                                                                                NULL);
3551                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3552                                                          mail_op);
3553
3554                         modest_mail_operation_xfer_folder (mail_op, 
3555                                                            TNY_FOLDER (src_folder),
3556                                                            dst_folder,
3557                                                            TRUE, NULL, NULL);
3558                         /* Unref mail operation */
3559                         g_object_unref (G_OBJECT (mail_op));
3560                 } else {
3561                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);       
3562                 }
3563         } else if (gtk_widget_is_focus (header_view)) {
3564                 /* Transfer messages */
3565                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3566         }
3567         
3568  end:
3569     if (src_folder)
3570         g_object_unref (src_folder);
3571 }
3572
3573
3574 /*
3575  * UI handler for the "Move to" action when invoked from the
3576  * ModestMsgViewWindow
3577  */
3578 static void 
3579 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
3580                                               TnyFolderStore *dst_folder,
3581                                               ModestMsgViewWindow *win)
3582 {
3583         TnyHeader *header = NULL;
3584         TnyFolder *src_folder;
3585
3586         /* Create header list */
3587         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
3588         src_folder = tny_header_get_folder(header);
3589         g_object_unref (header);
3590
3591         /* Transfer the message */
3592         if (modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (src_folder)))
3593                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3594
3595         g_object_unref (src_folder);
3596 }
3597
3598 void 
3599 modest_ui_actions_on_move_to (GtkAction *action, 
3600                               ModestWindow *win)
3601 {
3602         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
3603         gint result = 0;
3604         TnyFolderStore *dst_folder = NULL;
3605         ModestMainWindow *main_window;
3606
3607         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
3608                           MODEST_IS_MSG_VIEW_WINDOW (win));
3609
3610         /* Get the main window if exists */
3611         if (MODEST_IS_MAIN_WINDOW (win))
3612                 main_window = MODEST_MAIN_WINDOW (win);
3613         else
3614                 main_window = 
3615                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
3616
3617         /* Get the folder view widget if exists */
3618         if (main_window)
3619                 folder_view = modest_main_window_get_child_widget (main_window,
3620                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
3621         else
3622                 folder_view = NULL;
3623
3624         /* Create and run the dialog */
3625         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
3626         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
3627         result = gtk_dialog_run (GTK_DIALOG(dialog));
3628         g_object_ref (tree_view);
3629         gtk_widget_destroy (dialog);
3630
3631         if (result != GTK_RESPONSE_ACCEPT)
3632                 return;
3633
3634         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
3635         /* Offer the connection dialog if necessary: */
3636         if (modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
3637                                                                       dst_folder)) {
3638
3639                 /* Do window specific stuff */
3640                 if (MODEST_IS_MAIN_WINDOW (win))
3641                         modest_ui_actions_on_main_window_move_to (action,
3642                                                                   folder_view,
3643                                                                   dst_folder,
3644                                                                   MODEST_MAIN_WINDOW (win));
3645                 else
3646                         modest_ui_actions_on_msg_view_window_move_to (action,
3647                                                                       dst_folder,
3648                                                                       MODEST_MSG_VIEW_WINDOW (win));
3649         }
3650         if (dst_folder)
3651                 g_object_unref (dst_folder);
3652 }
3653
3654 /*
3655  * Calls #HeadersFunc for each header already selected in the main
3656  * window or the message currently being shown in the msg view window
3657  */
3658 static void
3659 do_headers_action (ModestWindow *win, 
3660                    HeadersFunc func,
3661                    gpointer user_data)
3662 {
3663         TnyList *headers_list;
3664         TnyIterator *iter;
3665         TnyHeader *header;
3666         TnyFolder *folder;
3667
3668         /* Get headers */
3669         headers_list = get_selected_headers (win);
3670         if (!headers_list)
3671                 return;
3672
3673         /* Get the folder */
3674         iter = tny_list_create_iterator (headers_list);
3675         header = TNY_HEADER (tny_iterator_get_current (iter));
3676         folder = tny_header_get_folder (header);
3677         g_object_unref (header);
3678
3679         /* Call the function for each header */
3680         while (!tny_iterator_is_done (iter)) {
3681                 header = TNY_HEADER (tny_iterator_get_current (iter));
3682                 func (header, win, user_data);
3683                 g_object_unref (header);
3684                 tny_iterator_next (iter);
3685         }
3686
3687         /* Trick: do a poke status in order to speed up the signaling
3688            of observers */
3689         tny_folder_poke_status (folder);
3690
3691         /* Frees */
3692         g_object_unref (folder);
3693         g_object_unref (iter);
3694         g_object_unref (headers_list);
3695 }
3696
3697 void 
3698 modest_ui_actions_view_attachment (GtkAction *action,
3699                                    ModestWindow *window)
3700 {
3701         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3702                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
3703         } else {
3704                 /* not supported window for this action */
3705                 g_return_if_reached ();
3706         }
3707 }
3708
3709 void
3710 modest_ui_actions_save_attachments (GtkAction *action,
3711                                     ModestWindow *window)
3712 {
3713         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3714                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
3715         } else {
3716                 /* not supported window for this action */
3717                 g_return_if_reached ();
3718         }
3719 }
3720
3721 void
3722 modest_ui_actions_remove_attachments (GtkAction *action,
3723                                       ModestWindow *window)
3724 {
3725         if (MODEST_IS_MAIN_WINDOW (window)) {
3726                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
3727         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3728                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
3729         } else {
3730                 /* not supported window for this action */
3731                 g_return_if_reached ();
3732         }
3733 }
3734
3735 void 
3736 modest_ui_actions_on_settings (GtkAction *action, 
3737                                ModestWindow *win)
3738 {
3739         GtkWidget *dialog;
3740
3741         dialog = modest_platform_get_global_settings_dialog ();
3742         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
3743         gtk_widget_show_all (dialog);
3744
3745         gtk_dialog_run (GTK_DIALOG (dialog));
3746
3747         gtk_widget_destroy (dialog);
3748 }
3749
3750 void 
3751 modest_ui_actions_on_help (GtkAction *action, 
3752                            ModestWindow *win)
3753 {
3754         const gchar *help_id = NULL;
3755
3756         if (MODEST_IS_MAIN_WINDOW (win)) {
3757                 const gchar *action_name;
3758                 action_name = gtk_action_get_name (action);
3759
3760                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
3761                     !strcmp (action_name, "HeaderViewCSMHelp")) {
3762                         GtkWidget *folder_view;
3763                         TnyFolderStore *folder_store;
3764                         /* Get selected folder */
3765                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3766                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3767                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3768
3769                         /* Switch help_id */
3770                         if (TNY_IS_FOLDER (folder_store)) {
3771                                 switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
3772                                 case TNY_FOLDER_TYPE_NORMAL:
3773                                         help_id = "applications_email_managefolders";
3774                                         break;
3775                                 case TNY_FOLDER_TYPE_INBOX:
3776                                         help_id = "applications_email_inbox";
3777                                         break;
3778                                 case TNY_FOLDER_TYPE_OUTBOX:
3779                                         help_id = "applications_email_outbox";
3780                                         break;
3781                                 case TNY_FOLDER_TYPE_SENT:
3782                                         help_id = "applications_email_sent";
3783                                         break;
3784                                 case TNY_FOLDER_TYPE_DRAFTS:
3785                                         help_id = "applications_email_drafts";
3786                                         break;
3787                                 case TNY_FOLDER_TYPE_ARCHIVE:
3788                                         help_id = "applications_email_managefolders";
3789                                         break;
3790                                 default:
3791                                         help_id = "applications_email_managefolders";
3792                                 }
3793                         } else {
3794                                 help_id = "applications_email_mainview";        
3795                         }
3796                         g_object_unref (folder_store);
3797                 } else {
3798                         help_id = "applications_email_mainview";        
3799                 }
3800         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3801                 help_id = "applications_email_viewer";
3802         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
3803                 help_id = "applications_email_editor";
3804
3805         modest_platform_show_help (GTK_WINDOW (win), help_id);
3806 }
3807
3808 void 
3809 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
3810                                             ModestWindow *window)
3811 {
3812         ModestMailOperation *mail_op;
3813         TnyList *headers;
3814
3815         /* Get headers */
3816         headers = get_selected_headers (window);
3817         if (!headers)
3818                 return;
3819
3820         /* Create mail operation */
3821         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3822                                                                  G_OBJECT (window),
3823                                                                  modest_ui_actions_get_msgs_full_error_handler, 
3824                                                                  NULL);
3825         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3826         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
3827
3828         /* Frees */
3829         g_object_unref (headers);
3830         g_object_unref (mail_op);
3831 }
3832
3833 void
3834 modest_ui_actions_on_email_menu_activated (GtkAction *action,
3835                                           ModestWindow *window)
3836 {
3837         g_return_if_fail (MODEST_IS_WINDOW (window));
3838
3839         /* Update dimmed */     
3840         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3841 }
3842
3843 void
3844 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
3845                                           ModestWindow *window)
3846 {
3847         g_return_if_fail (MODEST_IS_WINDOW (window));
3848
3849         /* Update dimmed */     
3850         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3851 }
3852
3853 void
3854 modest_ui_actions_on_view_menu_activated (GtkAction *action,
3855                                           ModestWindow *window)
3856 {
3857         g_return_if_fail (MODEST_IS_WINDOW (window));
3858
3859         /* Update dimmed */     
3860         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3861 }
3862
3863 void
3864 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
3865                                           ModestWindow *window)
3866 {
3867         g_return_if_fail (MODEST_IS_WINDOW (window));
3868
3869         /* Update dimmed */     
3870         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3871 }
3872
3873 void
3874 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
3875                                           ModestWindow *window)
3876 {
3877         g_return_if_fail (MODEST_IS_WINDOW (window));
3878
3879         /* Update dimmed */     
3880         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3881 }
3882
3883 void
3884 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
3885                                                  ModestWindow *window)
3886 {
3887         g_return_if_fail (MODEST_IS_WINDOW (window));
3888
3889         /* Update dimmed */     
3890         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3891 }
3892
3893 void
3894 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
3895                                                      ModestWindow *window)
3896 {
3897         g_return_if_fail (MODEST_IS_WINDOW (window));
3898
3899         /* Update dimmed */     
3900         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3901 }
3902
3903 void
3904 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
3905                                                      ModestWindow *window)
3906 {
3907         g_return_if_fail (MODEST_IS_WINDOW (window));
3908
3909         /* Update dimmed */     
3910         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3911 }
3912
3913 void
3914 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3915 {
3916         g_return_if_fail (MODEST_IS_WINDOW (window));
3917
3918         /* Update dimmed */     
3919         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
3920 }
3921
3922 void
3923 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
3924 {
3925         g_return_if_fail (MODEST_IS_WINDOW (window));
3926
3927         modest_platform_show_search_messages (GTK_WINDOW (window));
3928 }
3929
3930 void     
3931 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
3932 {
3933         g_return_if_fail (MODEST_IS_WINDOW (win));
3934         modest_platform_show_addressbook (GTK_WINDOW (win));
3935 }
3936
3937
3938 void
3939 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
3940                                           ModestWindow *window)
3941 {
3942         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3943
3944         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
3945 }
3946
3947 static void 
3948 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
3949                                    ModestMailOperationState *state,
3950                                    gpointer user_data)
3951 {
3952         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
3953
3954         /* Set send/receive operation finished */       
3955         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3956                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
3957         
3958 }
3959
3960