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