2007-07-22 Armin Burgmeier <armin@openismus.com>
[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 = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
732         if (!account)
733                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
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), NULL);
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, NULL);   
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                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1349
1350                         return;
1351                 }
1352
1353                 /* Show sorting dialog */
1354                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1355         }
1356 }
1357
1358 static void
1359 new_messages_arrived (ModestMailOperation *self, 
1360                       gint new_messages,
1361                       gpointer user_data)
1362 {
1363         if (new_messages == 0)
1364                 return;
1365
1366         modest_platform_on_new_msg ();
1367 }
1368
1369 /*
1370  * This function performs the send & receive required actions. The
1371  * window is used to create the mail operation. Typically it should
1372  * always be the main window, but we pass it as argument in order to
1373  * be more flexible.
1374  */
1375 void
1376 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1377 {
1378         gchar *acc_name = NULL;
1379         ModestMailOperation *mail_op;
1380
1381         /* If no account name was provided then get the current account, and if
1382            there is no current account then pick the default one: */
1383         if (!account_name) {
1384                 acc_name = g_strdup (modest_window_get_active_account(win));
1385                 if (!acc_name)
1386                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1387                 if (!acc_name) {
1388                         g_printerr ("modest: cannot get default account\n");
1389                         return;
1390                 }
1391         } else {
1392                 acc_name = g_strdup (account_name);
1393         }
1394
1395         /* Set send/receive operation in progress */    
1396         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1397
1398         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1399                                                                  G_OBJECT (win),
1400                                                                  modest_ui_actions_send_receive_error_handler,
1401                                                                  NULL);
1402
1403         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1404                           G_CALLBACK (_on_send_receive_progress_changed), 
1405                           win);
1406
1407         /* Send & receive. */
1408         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1409         /* Receive and then send. The operation is tagged initially as
1410            a receive operation because the account update performs a
1411            receive and then a send. The operation changes its type
1412            internally, so the progress objects will receive the proper
1413            progress information */
1414         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1415         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, NULL);
1416         g_object_unref (G_OBJECT (mail_op));
1417         
1418         /* Free */
1419         g_free (acc_name);
1420 }
1421
1422
1423 static void
1424 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1425                                   ModestWindow *win)
1426 {
1427         TnyTransportAccount *transport_account;
1428         TnySendQueue *send_queue = NULL;
1429         GError *error = NULL;
1430
1431         /* Get transport account */
1432         transport_account =
1433                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1434                                       (modest_runtime_get_account_store(),
1435                                        account_name,
1436                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1437         if (!transport_account) {
1438                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1439                 goto frees;
1440         }
1441
1442         /* Get send queue*/
1443         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1444         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1445                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1446                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1447                              "modest: could not find send queue for account\n");
1448         } else {
1449                 /* Keeep messages in outbox folder */
1450                 tny_send_queue_cancel (send_queue, FALSE, &error);
1451         }       
1452
1453  frees:
1454         if (transport_account != NULL) 
1455                 g_object_unref (G_OBJECT (transport_account));
1456 }
1457
1458 static void
1459 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1460 {
1461         GSList *account_names, *iter;
1462
1463         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1464                                                           TRUE);
1465
1466         iter = account_names;
1467         while (iter) {                  
1468                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1469                 iter = g_slist_next (iter);
1470         }
1471
1472         modest_account_mgr_free_account_names (account_names);
1473         account_names = NULL;
1474 }
1475
1476 void
1477 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1478
1479 {
1480         /* Check if accounts exist */
1481         gboolean accounts_exist = 
1482                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1483         
1484         /* If not, allow the user to create an account before trying to send/receive. */
1485         if (!accounts_exist)
1486                 modest_ui_actions_on_accounts (NULL, win);
1487         
1488         /* Cancel all sending operaitons */     
1489         modest_ui_actions_cancel_send_all (win);
1490 }
1491
1492 /*
1493  * Refreshes all accounts. This function will be used by automatic
1494  * updates
1495  */
1496 void
1497 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1498 {
1499         GSList *account_names, *iter;
1500
1501         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1502                                                           TRUE);
1503
1504         iter = account_names;
1505         while (iter) {                  
1506                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1507                 iter = g_slist_next (iter);
1508         }
1509
1510         modest_account_mgr_free_account_names (account_names);
1511         account_names = NULL;
1512 }
1513
1514 /*
1515  * Handler of the click on Send&Receive button in the main toolbar
1516  */
1517 void
1518 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
1519 {
1520         /* Check if accounts exist */
1521         gboolean accounts_exist = 
1522                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1523         
1524         /* If not, allow the user to create an account before trying to send/receive. */
1525         if (!accounts_exist)
1526                 modest_ui_actions_on_accounts (NULL, win);
1527
1528         /* Refresh currently selected folder. Note that if we only
1529            want to retrive the headers, then the refresh only will
1530            invoke a poke_status over all folders, i.e., only the
1531            total/unread count will be updated */
1532         if (MODEST_IS_MAIN_WINDOW (win)) {
1533                 GtkWidget *header_view, *folder_view;
1534                 TnyFolderStore *folder_store;
1535
1536                 /* Get folder and header view */
1537                 folder_view = 
1538                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1539                                                              MODEST_WIDGET_TYPE_FOLDER_VIEW);
1540
1541                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1542
1543                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1544                         header_view = 
1545                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1546                                                                      MODEST_WIDGET_TYPE_HEADER_VIEW);
1547                 
1548                         /* We do not need to set the contents style
1549                            because it hasn't changed. We also do not
1550                            need to save the widget status. Just force
1551                            a refresh */
1552                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1553                                                        TNY_FOLDER (folder_store),
1554                                                        folder_refreshed_cb,
1555                                                        MODEST_MAIN_WINDOW (win));
1556                 }
1557                 
1558                 if (folder_store)
1559                         g_object_unref (folder_store);
1560         }
1561         
1562         /* Refresh the active account */
1563         modest_ui_actions_do_send_receive (NULL, win);
1564 }
1565
1566
1567 void
1568 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1569 {
1570         ModestConf *conf;
1571         GtkWidget *header_view;
1572         
1573         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1574
1575         header_view = modest_main_window_get_child_widget (main_window,
1576                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1577         if (!header_view)
1578                 return;
1579
1580         conf = modest_runtime_get_conf ();
1581         
1582         /* what is saved/restored is depending on the style; thus; we save with
1583          * old style, then update the style, and restore for this new style
1584          */
1585         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1586         
1587         if (modest_header_view_get_style
1588             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1589                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1590                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1591         else
1592                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1593                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1594
1595         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1596                                       MODEST_CONF_HEADER_VIEW_KEY);
1597 }
1598
1599
1600 void 
1601 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1602                                       TnyHeader *header,
1603                                       ModestMainWindow *main_window)
1604 {
1605         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1606         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1607         
1608         /* If no header has been selected then exit */
1609         if (!header)
1610                 return;
1611
1612         /* Update focus */
1613         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1614             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1615
1616         /* Update Main window title */
1617         if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
1618                 const gchar *subject = tny_header_get_subject (header);
1619                 if (subject && strlen(subject) > 0)
1620                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
1621                 else
1622                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
1623         }
1624
1625         /* Update toolbar dimming state */
1626         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1627 }
1628
1629 void
1630 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1631                                        TnyHeader *header,
1632                                        ModestMainWindow *main_window)
1633 {
1634         TnyList *headers;
1635
1636         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1637         
1638         if (!header)
1639                 return;
1640
1641         headers = tny_simple_list_new ();
1642         tny_list_prepend (headers, G_OBJECT (header));
1643
1644         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1645
1646         g_object_unref (headers);
1647 }
1648
1649 static void
1650 set_active_account_from_tny_account (TnyAccount *account,
1651                                      ModestWindow *window)
1652 {
1653         const gchar *server_acc_name = tny_account_get_id (account);
1654         
1655         /* We need the TnyAccount provided by the
1656            account store because that is the one that
1657            knows the name of the Modest account */
1658         TnyAccount *modest_server_account = modest_server_account = 
1659                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1660                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1661                                                              server_acc_name);
1662         
1663         const gchar *modest_acc_name = 
1664                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1665         modest_window_set_active_account (window, modest_acc_name);
1666         g_object_unref (modest_server_account);
1667 }
1668
1669
1670 static void
1671 folder_refreshed_cb (ModestMailOperation *mail_op, 
1672                      TnyFolder *folder, 
1673                      gpointer user_data)
1674 {
1675         ModestMainWindow *win = NULL;
1676         GtkWidget *header_view;
1677         TnyFolder *current_folder;
1678
1679         g_return_if_fail (TNY_IS_FOLDER (folder));
1680
1681         win = MODEST_MAIN_WINDOW (user_data);
1682         header_view = 
1683                 modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
1684
1685         if (header_view) {
1686                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
1687                 if (current_folder != NULL && folder != current_folder) {
1688                         return;
1689                 }
1690         }
1691
1692         /* Check if folder is empty and set headers view contents style */
1693         if (tny_folder_get_all_count (folder) == 0) {
1694         printf ("DEBUG: %s: tny_folder_get_all_count() returned 0.\n", __FUNCTION__);
1695                 modest_main_window_set_contents_style (win,
1696                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1697         } else {
1698                 printf ("DEBUG: %s: tny_folder_get_all_count() returned >0.\n", __FUNCTION__);
1699         }
1700 }
1701
1702 void 
1703 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1704                                                TnyFolderStore *folder_store, 
1705                                                gboolean selected,
1706                                                ModestMainWindow *main_window)
1707 {
1708         ModestConf *conf;
1709         GtkWidget *header_view;
1710
1711         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1712
1713         header_view = modest_main_window_get_child_widget(main_window,
1714                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1715         if (!header_view)
1716                 return;
1717         
1718         conf = modest_runtime_get_conf ();
1719
1720         if (TNY_IS_ACCOUNT (folder_store)) {
1721                 if (selected) {
1722                         /* Update active account */
1723                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1724                         /* Show account details */
1725                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1726                 }
1727         } else {
1728                 if (TNY_IS_FOLDER (folder_store) && selected) {
1729                         
1730                         /* Update the active account */
1731                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1732                         if (account) {
1733                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1734                                 g_object_unref (account);
1735                                 account = NULL;
1736                         }
1737
1738                         /* Set the header style by default, it could
1739                            be changed later by the refresh callback to
1740                            empty */
1741                         modest_main_window_set_contents_style (main_window, 
1742                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1743
1744                         /* Set folder on header view. This function
1745                            will call tny_folder_refresh_async so we
1746                            pass a callback that will be called when
1747                            finished. We use that callback to set the
1748                            empty view if there are no messages */
1749                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1750                                                        TNY_FOLDER (folder_store),
1751                                                        folder_refreshed_cb,
1752                                                        main_window);
1753                         
1754                         /* Restore configuration. We need to do this
1755                            *after* the set_folder because the widget
1756                            memory asks the header view about its
1757                            folder  */
1758                         modest_widget_memory_restore (modest_runtime_get_conf (), 
1759                                                       G_OBJECT(header_view),
1760                                                       MODEST_CONF_HEADER_VIEW_KEY);
1761                 } else {
1762                         /* Update the active account */
1763                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1764                         /* Save only if we're seeing headers */
1765                         if (modest_main_window_get_contents_style (main_window) ==
1766                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1767                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
1768                                                            MODEST_CONF_HEADER_VIEW_KEY);
1769                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
1770                 }
1771         }
1772
1773         /* Update toolbar dimming state */
1774         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1775 }
1776
1777 void 
1778 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1779                                      ModestWindow *win)
1780 {
1781         GtkWidget *dialog;
1782         gchar *txt, *item;
1783         gboolean online;
1784
1785         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1786         
1787         online = tny_device_is_online (modest_runtime_get_device());
1788
1789         if (online) {
1790                 /* already online -- the item is simply not there... */
1791                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1792                                                  GTK_DIALOG_MODAL,
1793                                                  GTK_MESSAGE_WARNING,
1794                                                  GTK_BUTTONS_OK,
1795                                                  _("The %s you selected cannot be found"),
1796                                                  item);
1797                 gtk_dialog_run (GTK_DIALOG(dialog));
1798         } else {
1799                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1800                                                       GTK_WINDOW (win),
1801                                                       GTK_DIALOG_MODAL,
1802                                                       GTK_STOCK_CANCEL,
1803                                                       GTK_RESPONSE_REJECT,
1804                                                       GTK_STOCK_OK,
1805                                                       GTK_RESPONSE_ACCEPT,
1806                                                       NULL);
1807                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1808                                          "Do you want to get online?"), item);
1809                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1810                                     gtk_label_new (txt), FALSE, FALSE, 0);
1811                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1812                 g_free (txt);
1813
1814                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1815                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1816 //                      modest_platform_connect_and_wait ();
1817                 }
1818         }
1819         gtk_widget_destroy (dialog);
1820 }
1821
1822 void
1823 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1824                                      ModestWindow *win)
1825 {
1826         /* g_message ("%s %s", __FUNCTION__, link); */
1827 }       
1828
1829
1830 void
1831 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1832                                         ModestWindow *win)
1833 {
1834         modest_platform_activate_uri (link);
1835 }
1836
1837 void
1838 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1839                                           ModestWindow *win)
1840 {
1841         modest_platform_show_uri_popup (link);
1842 }
1843
1844 void
1845 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1846                                              ModestWindow *win)
1847 {
1848         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1849 }
1850
1851 void
1852 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1853                                           const gchar *address,
1854                                           ModestWindow *win)
1855 {
1856         /* g_message ("%s %s", __FUNCTION__, address); */
1857 }
1858
1859 void
1860 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1861 {
1862         TnyTransportAccount *transport_account;
1863         ModestMailOperation *mail_operation;
1864         MsgData *data;
1865         gchar *account_name, *from;
1866         ModestAccountMgr *account_mgr;
1867         gchar *info_text = NULL;
1868
1869         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1870         
1871         data = modest_msg_edit_window_get_msg_data (edit_window);
1872
1873         account_mgr = modest_runtime_get_account_mgr();
1874         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1875         if (!account_name) 
1876                 account_name = modest_account_mgr_get_default_account (account_mgr);
1877         if (!account_name) {
1878                 g_printerr ("modest: no account found\n");
1879                 modest_msg_edit_window_free_msg_data (edit_window, data);
1880                 return;
1881         }
1882
1883         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1884                 account_name = g_strdup (data->account_name);
1885         }
1886
1887         transport_account =
1888                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1889                                       (modest_runtime_get_account_store(),
1890                                        account_name,
1891                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1892         if (!transport_account) {
1893                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1894                 g_free (account_name);
1895                 modest_msg_edit_window_free_msg_data (edit_window, data);
1896                 return;
1897         }
1898         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1899
1900         /* Create the mail operation */         
1901         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1902         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1903
1904         modest_mail_operation_save_to_drafts (mail_operation,
1905                                               transport_account,
1906                                               data->draft_msg,
1907                                               edit_window,
1908                                               from,
1909                                               data->to, 
1910                                               data->cc, 
1911                                               data->bcc,
1912                                               data->subject, 
1913                                               data->plain_body, 
1914                                               data->html_body,
1915                                               data->attachments,
1916                                               data->priority_flags);
1917         /* Frees */
1918         g_free (from);
1919         g_free (account_name);
1920         g_object_unref (G_OBJECT (transport_account));
1921         g_object_unref (G_OBJECT (mail_operation));
1922
1923         modest_msg_edit_window_free_msg_data (edit_window, data);
1924
1925         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
1926         modest_platform_information_banner (NULL, NULL, info_text);
1927         g_free (info_text);
1928 }
1929
1930 /* For instance, when clicking the Send toolbar button when editing a message: */
1931 void
1932 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1933 {
1934         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1935
1936         if (!modest_msg_edit_window_check_names (edit_window))
1937                 return;
1938         
1939         /* Offer the connection dialog, if necessary: */        
1940         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window), NULL))
1941                 return;
1942         
1943         /* FIXME: Code added just for testing. The final version will
1944            use the send queue provided by tinymail and some
1945            classifier */
1946         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
1947         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1948         if (!account_name) 
1949                 account_name = modest_account_mgr_get_default_account (account_mgr);
1950                 
1951         if (!account_name) {
1952                 g_printerr ("modest: no account found\n");
1953                 return;
1954         }
1955         
1956         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
1957
1958         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1959                 account_name = g_strdup (data->account_name);
1960         }
1961         
1962         /* Get the currently-active transport account for this modest account: */
1963         TnyTransportAccount *transport_account =
1964                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1965                                       (modest_runtime_get_account_store(),
1966                                        account_name));
1967         if (!transport_account) {
1968                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1969                 g_free (account_name);
1970                 modest_msg_edit_window_free_msg_data (edit_window, data);
1971                 return;
1972         }
1973         
1974         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
1975
1976         /* mail content checks and dialogs */
1977         if (data->subject == NULL || data->subject[0] == '\0') {
1978                 GtkResponseType response;
1979                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1980                                                                     _("mcen_nc_subject_is_empty_send"));
1981                 if (response == GTK_RESPONSE_CANCEL) {
1982                         g_free (account_name);
1983                         return;
1984                 }
1985         }
1986
1987         if (data->plain_body == NULL || data->plain_body[0] == '\0') {
1988                 GtkResponseType response;
1989                 gchar *note_message;
1990                 gchar *note_subject = data->subject;
1991                 if (note_subject == NULL || note_subject[0] == '\0')
1992                         note_subject = _("mail_va_no_subject");
1993                 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
1994                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1995                                                                     note_message);
1996                 g_free (note_message);
1997                 if (response == GTK_RESPONSE_CANCEL) {
1998                         g_free (account_name);
1999                         return;
2000                 }
2001         }
2002
2003         modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2004
2005         /* Create the mail operation */
2006         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
2007         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2008
2009         modest_mail_operation_send_new_mail (mail_operation,
2010                                              transport_account,
2011                                              data->draft_msg,
2012                                              from,
2013                                              data->to, 
2014                                              data->cc, 
2015                                              data->bcc,
2016                                              data->subject, 
2017                                              data->plain_body, 
2018                                              data->html_body,
2019                                              data->attachments,
2020                                              data->priority_flags);
2021                                              
2022         /* Free data: */
2023         g_free (from);
2024         g_free (account_name);
2025         g_object_unref (G_OBJECT (transport_account));
2026         g_object_unref (G_OBJECT (mail_operation));
2027
2028         modest_msg_edit_window_free_msg_data (edit_window, data);
2029         modest_msg_edit_window_set_sent (edit_window, TRUE);
2030
2031         /* Save settings and close the window: */
2032         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2033 }
2034
2035 void 
2036 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2037                                   ModestMsgEditWindow *window)
2038 {
2039         ModestMsgEditFormatState *format_state = NULL;
2040
2041         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2042         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2043
2044         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2045                 return;
2046
2047         format_state = modest_msg_edit_window_get_format_state (window);
2048         g_return_if_fail (format_state != NULL);
2049
2050         format_state->bold = gtk_toggle_action_get_active (action);
2051         modest_msg_edit_window_set_format_state (window, format_state);
2052         g_free (format_state);
2053         
2054 }
2055
2056 void 
2057 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2058                                      ModestMsgEditWindow *window)
2059 {
2060         ModestMsgEditFormatState *format_state = NULL;
2061
2062         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2063         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2064
2065         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2066                 return;
2067
2068         format_state = modest_msg_edit_window_get_format_state (window);
2069         g_return_if_fail (format_state != NULL);
2070
2071         format_state->italics = gtk_toggle_action_get_active (action);
2072         modest_msg_edit_window_set_format_state (window, format_state);
2073         g_free (format_state);
2074         
2075 }
2076
2077 void 
2078 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2079                                      ModestMsgEditWindow *window)
2080 {
2081         ModestMsgEditFormatState *format_state = NULL;
2082
2083         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2084         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2085
2086         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2087                 return;
2088
2089         format_state = modest_msg_edit_window_get_format_state (window);
2090         g_return_if_fail (format_state != NULL);
2091
2092         format_state->bullet = gtk_toggle_action_get_active (action);
2093         modest_msg_edit_window_set_format_state (window, format_state);
2094         g_free (format_state);
2095         
2096 }
2097
2098 void 
2099 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2100                                      GtkRadioAction *selected,
2101                                      ModestMsgEditWindow *window)
2102 {
2103         ModestMsgEditFormatState *format_state = NULL;
2104         GtkJustification value;
2105
2106         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2107
2108         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2109                 return;
2110
2111         value = gtk_radio_action_get_current_value (selected);
2112
2113         format_state = modest_msg_edit_window_get_format_state (window);
2114         g_return_if_fail (format_state != NULL);
2115
2116         format_state->justification = value;
2117         modest_msg_edit_window_set_format_state (window, format_state);
2118         g_free (format_state);
2119 }
2120
2121 void 
2122 modest_ui_actions_on_select_editor_color (GtkAction *action,
2123                                           ModestMsgEditWindow *window)
2124 {
2125         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2126         g_return_if_fail (GTK_IS_ACTION (action));
2127
2128         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2129                 return;
2130
2131         modest_msg_edit_window_select_color (window);
2132 }
2133
2134 void 
2135 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2136                                                      ModestMsgEditWindow *window)
2137 {
2138         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2139         g_return_if_fail (GTK_IS_ACTION (action));
2140
2141         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2142                 return;
2143
2144         modest_msg_edit_window_select_background_color (window);
2145 }
2146
2147 void 
2148 modest_ui_actions_on_insert_image (GtkAction *action,
2149                                    ModestMsgEditWindow *window)
2150 {
2151         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2152         g_return_if_fail (GTK_IS_ACTION (action));
2153
2154         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2155                 return;
2156
2157         modest_msg_edit_window_insert_image (window);
2158 }
2159
2160 void 
2161 modest_ui_actions_on_attach_file (GtkAction *action,
2162                                   ModestMsgEditWindow *window)
2163 {
2164         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2165         g_return_if_fail (GTK_IS_ACTION (action));
2166
2167         modest_msg_edit_window_attach_file (window);
2168 }
2169
2170 void 
2171 modest_ui_actions_on_remove_attachments (GtkAction *action,
2172                                          ModestMsgEditWindow *window)
2173 {
2174         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2175         g_return_if_fail (GTK_IS_ACTION (action));
2176
2177         modest_msg_edit_window_remove_attachments (window, NULL);
2178 }
2179
2180 static void
2181 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2182                                             gpointer user_data)
2183 {
2184         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2185         const GError *error = modest_mail_operation_get_error (mail_op);
2186
2187         if(error)
2188         {
2189                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2190                                                     modest_mail_operation_get_error (mail_op)->message);
2191         }
2192 }
2193
2194 static void
2195 modest_ui_actions_create_folder(GtkWidget *parent_window,
2196                                 GtkWidget *folder_view)
2197 {
2198         TnyFolderStore *parent_folder;
2199
2200         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2201         
2202         if (parent_folder) {
2203                 gboolean finished = FALSE;
2204                 gint result;
2205                 gchar *folder_name = NULL, *suggested_name = NULL;
2206
2207                 /* Run the new folder dialog */
2208                 while (!finished) {
2209                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2210                                                                         parent_folder,
2211                                                                         suggested_name,
2212                                                                         &folder_name);
2213
2214                         g_free (suggested_name);
2215                         suggested_name = NULL;
2216
2217                         if (result == GTK_RESPONSE_REJECT) {
2218                                 finished = TRUE;
2219                         } else {
2220                                 ModestMailOperation *mail_op;
2221                                 TnyFolder *new_folder = NULL;
2222
2223                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2224                                                                                           G_OBJECT(parent_window),
2225                                                                                           modest_ui_actions_new_folder_error_handler,
2226                                                                                           parent_window);
2227
2228                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2229                                                                  mail_op);
2230                                 new_folder = modest_mail_operation_create_folder (mail_op,
2231                                                                                   parent_folder,
2232                                                                                   (const gchar *) folder_name);
2233                                 if (new_folder) {
2234                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2235                                                                           new_folder, TRUE);
2236
2237                                         g_object_unref (new_folder);
2238                                         finished = TRUE;
2239                                 }
2240                                 g_object_unref (mail_op);
2241                         }
2242
2243                         suggested_name = folder_name;
2244                         folder_name = NULL;
2245                 }
2246
2247                 g_object_unref (parent_folder);
2248         }
2249 }
2250
2251 void 
2252 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2253 {
2254         GtkWidget *folder_view;
2255         
2256         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2257
2258         folder_view = modest_main_window_get_child_widget (main_window,
2259                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2260         if (!folder_view)
2261                 return;
2262
2263         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2264 }
2265
2266 static void
2267 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2268                                                gpointer user_data)
2269 {
2270         GObject *win = modest_mail_operation_get_source (mail_op);
2271         const GError *error = NULL;
2272         const gchar *message = NULL;
2273         
2274         /* Get error message */
2275         error = modest_mail_operation_get_error (mail_op);
2276         if (error != NULL && error->message != NULL) {
2277                 message = error->message;
2278         } else {
2279                 message = _("!!! FIXME: Unable to rename");
2280         }
2281         
2282         /* Show notification dialog */
2283         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
2284         g_object_unref (win);
2285 }
2286
2287 void 
2288 modest_ui_actions_on_rename_folder (GtkAction *action,
2289                                      ModestMainWindow *main_window)
2290 {
2291         TnyFolderStore *folder;
2292         GtkWidget *folder_view;
2293         GtkWidget *header_view; 
2294
2295         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2296
2297         folder_view = modest_main_window_get_child_widget (main_window,
2298                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2299         if (!folder_view)
2300                 return;
2301
2302         header_view = modest_main_window_get_child_widget (main_window,
2303                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2304         
2305         if (!header_view)
2306                 return;
2307
2308         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2309         if (!folder)
2310                 return;
2311
2312         /* Offer the connection dialog if necessary: */
2313         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2314                 g_object_unref (G_OBJECT (folder));
2315                 return;
2316         }
2317
2318         
2319         if (TNY_IS_FOLDER (folder)) {
2320                 gchar *folder_name;
2321                 gint response;
2322                 const gchar *current_name;
2323
2324                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2325                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), NULL,
2326                                                                      current_name, &folder_name);
2327
2328                 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2329                         ModestMailOperation *mail_op;
2330
2331                         mail_op = 
2332                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO, 
2333                                                                                G_OBJECT(main_window),
2334                                                                                modest_ui_actions_rename_folder_error_handler,
2335                                                                                NULL);
2336
2337
2338                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2339                                                          mail_op);
2340
2341                         modest_header_view_clear (MODEST_HEADER_VIEW (header_view));
2342                         
2343                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2344                                                           TNY_FOLDER(folder), TRUE);
2345
2346
2347                         modest_header_view_clear ((ModestHeaderView *) header_view);
2348  
2349                         modest_mail_operation_rename_folder (mail_op,
2350                                                              TNY_FOLDER (folder),
2351                                                              (const gchar *) folder_name);
2352
2353                         g_object_unref (mail_op);
2354                         g_free (folder_name);
2355                 }
2356         }
2357         g_object_unref (folder);
2358 }
2359
2360 static void
2361 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2362                                                gpointer user_data)
2363 {
2364         GObject *win = modest_mail_operation_get_source (mail_op);
2365
2366         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2367                                                 _("mail_in_ui_folder_delete_error"));
2368         g_object_unref (win);
2369 }
2370
2371 static void
2372 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2373 {
2374         TnyFolderStore *folder;
2375         GtkWidget *folder_view;
2376         gint response;
2377         gchar *message;
2378         
2379         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2380
2381         folder_view = modest_main_window_get_child_widget (main_window,
2382                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2383         if (!folder_view)
2384                 return;
2385
2386         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2387
2388         /* Show an error if it's an account */
2389         if (!TNY_IS_FOLDER (folder)) {
2390                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2391                                                         _("mail_in_ui_folder_delete_error"));
2392                 g_object_unref (G_OBJECT (folder));
2393                 return ;
2394         }
2395
2396         /* Offer the connection dialog if necessary: */
2397         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2398                 g_object_unref (G_OBJECT (folder));
2399                 return;
2400         }
2401
2402         /* Ask the user */      
2403         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2404                                     tny_folder_get_name (TNY_FOLDER (folder)));
2405         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2406                                                             (const gchar *) message);
2407         g_free (message);
2408
2409         if (response == GTK_RESPONSE_OK) {
2410                 ModestMailOperation *mail_op = 
2411                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2412                                                                        G_OBJECT(main_window),
2413                                                                        modest_ui_actions_delete_folder_error_handler,
2414                                                                        NULL);
2415
2416                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2417                                                  mail_op);
2418                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2419                 g_object_unref (G_OBJECT (mail_op));
2420         }
2421
2422         g_object_unref (G_OBJECT (folder));
2423 }
2424
2425 void 
2426 modest_ui_actions_on_delete_folder (GtkAction *action,
2427                                      ModestMainWindow *main_window)
2428 {
2429         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2430
2431         delete_folder (main_window, FALSE);
2432 }
2433
2434 void 
2435 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2436 {
2437         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2438         
2439         delete_folder (main_window, TRUE);
2440 }
2441
2442 void
2443 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2444                                          const gchar* server_account_name,
2445                                          gchar **username,
2446                                          gchar **password, 
2447                                          gboolean *cancel, 
2448                                          gboolean *remember,
2449                                          ModestMainWindow *main_window)
2450 {
2451         g_return_if_fail(server_account_name);
2452         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2453         
2454         /* Initalize output parameters: */
2455         if (cancel)
2456                 *cancel = FALSE;
2457                 
2458         if (remember)
2459                 *remember = TRUE;
2460                 
2461 #ifdef MODEST_PLATFORM_MAEMO
2462         /* Maemo uses a different (awkward) button order,
2463          * It should probably just use gtk_alternative_dialog_button_order ().
2464          */
2465         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2466                                               NULL,
2467                                               GTK_DIALOG_MODAL,
2468                                               GTK_STOCK_OK,
2469                                               GTK_RESPONSE_ACCEPT,
2470                                               GTK_STOCK_CANCEL,
2471                                               GTK_RESPONSE_REJECT,
2472                                               NULL);
2473 #else
2474         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2475                                               NULL,
2476                                               GTK_DIALOG_MODAL,
2477                                               GTK_STOCK_CANCEL,
2478                                               GTK_RESPONSE_REJECT,
2479                                               GTK_STOCK_OK,
2480                                               GTK_RESPONSE_ACCEPT,
2481                                               NULL);
2482 #endif /* MODEST_PLATFORM_MAEMO */
2483
2484         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2485         
2486         gchar *server_name = modest_server_account_get_hostname (
2487                 modest_runtime_get_account_mgr(), server_account_name);
2488         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2489                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2490                 *cancel = TRUE;
2491                 return;
2492         }
2493         
2494         /* This causes a warning because the logical ID has no %s in it, 
2495          * though the translation does, but there is not much we can do about that: */
2496         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2497         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2498                             FALSE, FALSE, 0);
2499         g_free (txt);
2500         g_free (server_name);
2501         server_name = NULL;
2502
2503         /* username: */
2504         gchar *initial_username = modest_server_account_get_username (
2505                 modest_runtime_get_account_mgr(), server_account_name);
2506         
2507         GtkWidget *entry_username = gtk_entry_new ();
2508         if (initial_username)
2509                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2510         /* Dim this if a connection has ever succeeded with this username,
2511          * as per the UI spec: */
2512         const gboolean username_known = 
2513                 modest_server_account_get_username_has_succeeded(
2514                         modest_runtime_get_account_mgr(), server_account_name);
2515         gtk_widget_set_sensitive (entry_username, !username_known);
2516         
2517 #ifdef MODEST_PLATFORM_MAEMO
2518         /* Auto-capitalization is the default, so let's turn it off: */
2519         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2520         
2521         /* Create a size group to be used by all captions.
2522          * Note that HildonCaption does not create a default size group if we do not specify one.
2523          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2524         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2525         
2526         GtkWidget *caption = hildon_caption_new (sizegroup, 
2527                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2528         gtk_widget_show (entry_username);
2529         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2530                 FALSE, FALSE, MODEST_MARGIN_HALF);
2531         gtk_widget_show (caption);
2532 #else 
2533         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2534                             TRUE, FALSE, 0);
2535 #endif /* MODEST_PLATFORM_MAEMO */      
2536                             
2537         /* password: */
2538         GtkWidget *entry_password = gtk_entry_new ();
2539         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2540         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2541         
2542 #ifdef MODEST_PLATFORM_MAEMO
2543         /* Auto-capitalization is the default, so let's turn it off: */
2544         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2545                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2546         
2547         caption = hildon_caption_new (sizegroup, 
2548                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2549         gtk_widget_show (entry_password);
2550         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2551                 FALSE, FALSE, MODEST_MARGIN_HALF);
2552         gtk_widget_show (caption);
2553         g_object_unref (sizegroup);
2554 #else 
2555         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2556                             TRUE, FALSE, 0);
2557 #endif /* MODEST_PLATFORM_MAEMO */      
2558                                 
2559 /* This is not in the Maemo UI spec:
2560         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2561         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2562                             TRUE, FALSE, 0);
2563 */
2564
2565         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2566         
2567         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2568                 if (username) {
2569                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2570                         
2571                         modest_server_account_set_username (
2572                                  modest_runtime_get_account_mgr(), server_account_name, 
2573                                  *username);
2574                                  
2575                         const gboolean username_was_changed = 
2576                                 (strcmp (*username, initial_username) != 0);
2577                         if (username_was_changed) {
2578                                 g_warning ("%s: tinymail does not yet support changing the "
2579                                         "username in the get_password() callback.\n", __FUNCTION__);
2580                         }
2581                 }
2582                         
2583                 if (password) {
2584                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2585                         
2586                         /* We do not save the password in the configuration, 
2587                          * because this function is only called for passwords that should 
2588                          * not be remembered:
2589                         modest_server_account_set_password (
2590                                  modest_runtime_get_account_mgr(), server_account_name, 
2591                                  *password);
2592                         */
2593                 }
2594                 
2595                 if (cancel)
2596                         *cancel   = FALSE;
2597                         
2598         } else {
2599                 if (username)
2600                         *username = NULL;
2601                         
2602                 if (password)
2603                         *password = NULL;
2604                         
2605                 if (cancel)
2606                         *cancel   = TRUE;
2607         }
2608
2609 /* This is not in the Maemo UI spec:
2610         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2611                 *remember = TRUE;
2612         else
2613                 *remember = FALSE;
2614 */
2615
2616         gtk_widget_destroy (dialog);
2617         
2618         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2619 }
2620
2621 void
2622 modest_ui_actions_on_cut (GtkAction *action,
2623                           ModestWindow *window)
2624 {
2625         GtkWidget *focused_widget;
2626
2627         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2628         if (GTK_IS_EDITABLE (focused_widget)) {
2629                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2630         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2631                 GtkTextBuffer *buffer;
2632                 GtkClipboard *clipboard;
2633
2634                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2635                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2636                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2637                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2638         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2639                 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2640         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2641                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2642         }
2643 }
2644
2645 void
2646 modest_ui_actions_on_copy (GtkAction *action,
2647                            ModestWindow *window)
2648 {
2649         GtkClipboard *clipboard;
2650         GtkWidget *focused_widget;
2651
2652         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2653         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2654
2655         if (GTK_IS_LABEL (focused_widget)) {
2656                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2657         } else if (GTK_IS_EDITABLE (focused_widget)) {
2658                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2659         } else if (GTK_IS_HTML (focused_widget)) {
2660                 gtk_html_copy (GTK_HTML (focused_widget));
2661         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2662                 GtkTextBuffer *buffer;
2663                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2664                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2665                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2666         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2667                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2668                 TnyIterator *iter = tny_list_create_iterator (header_list);
2669                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2670                 TnyFolder *folder = tny_header_get_folder (header);
2671                 TnyAccount *account = tny_folder_get_account (folder);
2672                 const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2673                 /* If it's POP then ask */
2674                 gboolean ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2675                        MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2676                 g_object_unref (account);
2677                 g_object_unref (folder);
2678                 g_object_unref (header);
2679                 g_object_unref (iter);
2680                 
2681                 /* Check that the messages have been previously downloaded */
2682                 gboolean continue_download = TRUE;
2683                 if (ask)
2684                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window), FALSE);
2685                 if (continue_download)
2686                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2687                 g_object_unref (header_list);
2688         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2689                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2690         }    
2691
2692         /* Show information banner */
2693         modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2694         
2695 }
2696
2697 void
2698 modest_ui_actions_on_undo (GtkAction *action,
2699                            ModestWindow *window)
2700 {
2701         ModestEmailClipboard *clipboard = NULL;
2702
2703         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2704                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2705         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2706                 /* Clear clipboard source */
2707                 clipboard = modest_runtime_get_email_clipboard ();
2708                 modest_email_clipboard_clear (clipboard);               
2709         }
2710         else {
2711                 g_return_if_reached ();
2712         }
2713 }
2714
2715 void
2716 modest_ui_actions_on_redo (GtkAction *action,
2717                            ModestWindow *window)
2718 {
2719         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2720                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2721         }
2722         else {
2723                 g_return_if_reached ();
2724         }
2725 }
2726
2727
2728 static void
2729 paste_msgs_cb (const GObject *object, gpointer user_data)
2730 {
2731         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2732         g_return_if_fail (GTK_IS_WIDGET (user_data));
2733         
2734         /* destroy information note */
2735         gtk_widget_destroy (GTK_WIDGET(user_data));
2736 }
2737
2738 void
2739 modest_ui_actions_on_paste (GtkAction *action,
2740                             ModestWindow *window)
2741 {
2742         GtkWidget *focused_widget = NULL;
2743         GtkWidget *inf_note = NULL;
2744         ModestMailOperation *mail_op = NULL;
2745
2746         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2747         if (GTK_IS_EDITABLE (focused_widget)) {
2748                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2749         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2750                 GtkTextBuffer *buffer;
2751                 GtkClipboard *clipboard;
2752
2753                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2754                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2755                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2756         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2757                 ModestEmailClipboard *clipboard = NULL;
2758                 TnyFolder *src_folder = NULL;
2759                 TnyFolderStore *folder_store = NULL;
2760                 TnyList *data = NULL;           
2761                 gboolean delete = FALSE;
2762                 
2763                 /* Check clipboard source */
2764                 clipboard = modest_runtime_get_email_clipboard ();
2765                 if (modest_email_clipboard_cleared (clipboard)) 
2766                         return;
2767                 
2768                 /* Get elements to paste */
2769                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
2770
2771                 /* Create a new mail operation */
2772                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
2773                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2774                                                  mail_op);
2775                 
2776                 /* Get destination folder */
2777                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
2778
2779                 /* Launch notification */
2780                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
2781                                                              _CS("ckct_nw_pasting"));
2782                 if (inf_note != NULL)  {
2783                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
2784                         gtk_widget_show (GTK_WIDGET(inf_note));
2785                 }
2786
2787                 /* transfer messages  */
2788                 if (data != NULL) {
2789                         modest_mail_operation_xfer_msgs (mail_op, 
2790                                                          data,
2791                                                          TNY_FOLDER (folder_store),
2792                                                          delete,
2793                                                          paste_msgs_cb,
2794                                                          inf_note);
2795                         
2796                 } else if (src_folder != NULL) {                        
2797                         modest_mail_operation_xfer_folder (mail_op, 
2798                                                            src_folder,
2799                                                            folder_store,
2800                                                            delete,
2801                                                            paste_msgs_cb,
2802                                                            inf_note);
2803                 }
2804
2805                 /* Free */
2806                 if (data != NULL) 
2807                         g_object_unref (data);
2808                 if (src_folder != NULL) 
2809                         g_object_unref (src_folder);
2810                 if (folder_store != NULL) 
2811                         g_object_unref (folder_store);
2812         }
2813 }
2814
2815
2816 void
2817 modest_ui_actions_on_select_all (GtkAction *action,
2818                                  ModestWindow *window)
2819 {
2820         GtkWidget *focused_widget;
2821
2822         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2823         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2824                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2825         } else if (GTK_IS_LABEL (focused_widget)) {
2826                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2827         } else if (GTK_IS_EDITABLE (focused_widget)) {
2828                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2829         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2830                 GtkTextBuffer *buffer;
2831                 GtkTextIter start, end;
2832
2833                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2834                 gtk_text_buffer_get_start_iter (buffer, &start);
2835                 gtk_text_buffer_get_end_iter (buffer, &end);
2836                 gtk_text_buffer_select_range (buffer, &start, &end);
2837         } else if (GTK_IS_HTML (focused_widget)) {
2838                 gtk_html_select_all (GTK_HTML (focused_widget));
2839         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2840                 GtkWidget *header_view = focused_widget;
2841                 GtkTreeSelection *selection = NULL;
2842                 
2843                 if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
2844                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2845                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2846                                 
2847                 /* Select all messages */
2848                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2849                 gtk_tree_selection_select_all (selection);
2850
2851                 /* Set focuse on header view */
2852                 gtk_widget_grab_focus (header_view);
2853         }
2854
2855 }
2856
2857 void
2858 modest_ui_actions_on_mark_as_read (GtkAction *action,
2859                                    ModestWindow *window)
2860 {       
2861         g_return_if_fail (MODEST_IS_WINDOW(window));
2862                 
2863         /* Mark each header as read */
2864         do_headers_action (window, headers_action_mark_as_read, NULL);
2865 }
2866
2867 void
2868 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2869                                      ModestWindow *window)
2870 {       
2871         g_return_if_fail (MODEST_IS_WINDOW(window));
2872                 
2873         /* Mark each header as read */
2874         do_headers_action (window, headers_action_mark_as_unread, NULL);
2875 }
2876
2877 void
2878 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2879                                   GtkRadioAction *selected,
2880                                   ModestWindow *window)
2881 {
2882         gint value;
2883
2884         value = gtk_radio_action_get_current_value (selected);
2885         if (MODEST_IS_WINDOW (window)) {
2886                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2887         }
2888 }
2889
2890 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2891                                                         GtkRadioAction *selected,
2892                                                         ModestWindow *window)
2893 {
2894         TnyHeaderFlags flags;
2895         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2896
2897         flags = gtk_radio_action_get_current_value (selected);
2898         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2899 }
2900
2901 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2902                                                            GtkRadioAction *selected,
2903                                                            ModestWindow *window)
2904 {
2905         gint file_format;
2906
2907         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2908
2909         file_format = gtk_radio_action_get_current_value (selected);
2910         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2911 }
2912
2913
2914 void     
2915 modest_ui_actions_on_zoom_plus (GtkAction *action,
2916                                 ModestWindow *window)
2917 {
2918         g_return_if_fail (MODEST_IS_WINDOW (window));
2919
2920         modest_window_zoom_plus (MODEST_WINDOW (window));
2921 }
2922
2923 void     
2924 modest_ui_actions_on_zoom_minus (GtkAction *action,
2925                                  ModestWindow *window)
2926 {
2927         g_return_if_fail (MODEST_IS_WINDOW (window));
2928
2929         modest_window_zoom_minus (MODEST_WINDOW (window));
2930 }
2931
2932 void     
2933 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2934                                            ModestWindow *window)
2935 {
2936         ModestWindowMgr *mgr;
2937         gboolean fullscreen, active;
2938         g_return_if_fail (MODEST_IS_WINDOW (window));
2939
2940         mgr = modest_runtime_get_window_mgr ();
2941
2942         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2943         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2944
2945         if (active != fullscreen) {
2946                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2947                 gtk_window_present (GTK_WINDOW (window));
2948         }
2949 }
2950
2951 void
2952 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2953                                         ModestWindow *window)
2954 {
2955         ModestWindowMgr *mgr;
2956         gboolean fullscreen;
2957
2958         g_return_if_fail (MODEST_IS_WINDOW (window));
2959
2960         mgr = modest_runtime_get_window_mgr ();
2961         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2962         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2963
2964         gtk_window_present (GTK_WINDOW (window));
2965 }
2966
2967 /* 
2968  * Used by modest_ui_actions_on_details to call do_headers_action 
2969  */
2970 static void
2971 headers_action_show_details (TnyHeader *header, 
2972                              ModestWindow *window,
2973                              gpointer user_data)
2974
2975 {
2976         GtkWidget *dialog;
2977         
2978         /* Create dialog */
2979         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2980
2981         /* Run dialog */
2982         gtk_widget_show_all (dialog);
2983         gtk_dialog_run (GTK_DIALOG (dialog));
2984
2985         gtk_widget_destroy (dialog);
2986 }
2987
2988 /*
2989  * Show the folder details in a ModestDetailsDialog widget
2990  */
2991 static void
2992 show_folder_details (TnyFolder *folder, 
2993                      GtkWindow *window)
2994 {
2995         GtkWidget *dialog;
2996         
2997         /* Create dialog */
2998         dialog = modest_details_dialog_new_with_folder (window, folder);
2999
3000         /* Run dialog */
3001         gtk_widget_show_all (dialog);
3002         gtk_dialog_run (GTK_DIALOG (dialog));
3003
3004         gtk_widget_destroy (dialog);
3005 }
3006
3007 /*
3008  * Show the header details in a ModestDetailsDialog widget
3009  */
3010 void     
3011 modest_ui_actions_on_details (GtkAction *action, 
3012                               ModestWindow *win)
3013 {
3014         TnyList * headers_list;
3015         TnyIterator *iter;
3016         TnyHeader *header;              
3017
3018         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3019                 TnyMsg *msg;
3020
3021                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3022                 if (!msg)
3023                         return;
3024                 g_object_unref (msg);           
3025
3026                 headers_list = get_selected_headers (win);
3027                 if (!headers_list)
3028                         return;
3029
3030                 iter = tny_list_create_iterator (headers_list);
3031
3032                 header = TNY_HEADER (tny_iterator_get_current (iter));
3033                 headers_action_show_details (header, win, NULL);
3034                 g_object_unref (header);
3035
3036                 g_object_unref (iter);
3037                 g_object_unref (headers_list);
3038
3039         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3040                 GtkWidget *folder_view, *header_view;
3041
3042                 /* Check which widget has the focus */
3043                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3044                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
3045                 if (gtk_widget_is_focus (folder_view)) {
3046                         TnyFolderStore *folder_store
3047                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3048                         if (!folder_store) {
3049                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3050                                 return; 
3051                         }
3052                         /* Show only when it's a folder */
3053                         /* This function should not be called for account items, 
3054                          * because we dim the menu item for them. */
3055                         if (TNY_IS_FOLDER (folder_store)) {
3056                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3057                         }
3058
3059                         g_object_unref (folder_store);
3060
3061                 } else {
3062                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3063                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3064                         /* Show details of each header */
3065                         do_headers_action (win, headers_action_show_details, header_view);
3066                 }
3067         }
3068 }
3069
3070 void     
3071 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3072                                      ModestMsgEditWindow *window)
3073 {
3074         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3075
3076         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3077 }
3078
3079 void     
3080 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3081                                       ModestMsgEditWindow *window)
3082 {
3083         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3084
3085         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3086 }
3087
3088 void
3089 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3090                                        ModestMainWindow *main_window)
3091 {
3092         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3093
3094         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3095                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3096         else
3097                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3098 }
3099
3100 void 
3101 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3102                                      ModestWindow *window)
3103 {
3104         gboolean active, fullscreen = FALSE;
3105         ModestWindowMgr *mgr;
3106
3107         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3108
3109         /* Check if we want to toggle the toolbar vuew in fullscreen
3110            or normal mode */
3111         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3112                      "ViewShowToolbarFullScreen")) {
3113                 fullscreen = TRUE;
3114         }
3115
3116         /* Toggle toolbar */
3117         mgr = modest_runtime_get_window_mgr ();
3118         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
3119 }
3120
3121 void     
3122 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3123                                            ModestMsgEditWindow *window)
3124 {
3125         modest_msg_edit_window_select_font (window);
3126 }
3127
3128 void
3129 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3130                                                   const gchar *display_name,
3131                                                   GtkWindow *window)
3132 {
3133         /* Do not change the application name if the widget has not
3134            the focus. This callback could be called even if the folder
3135            view has not the focus, because the handled signal could be
3136            emitted when the folder view is redrawn */
3137         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3138                 if (display_name)
3139                         gtk_window_set_title (window, display_name);
3140                 else
3141                         gtk_window_set_title (window, " ");
3142         }
3143 }
3144
3145 void
3146 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3147 {
3148         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3149         modest_msg_edit_window_select_contacts (window);
3150 }
3151
3152 void
3153 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3154 {
3155         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3156         modest_msg_edit_window_check_names (window);
3157 }
3158
3159 static void
3160 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3161 {
3162         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3163                                          GTK_WIDGET (user_data));
3164 }
3165
3166 static GtkWidget*
3167 create_move_to_dialog (GtkWindow *win,
3168                        GtkWidget *folder_view,
3169                        GtkWidget **tree_view)
3170 {
3171         GtkWidget *dialog, *scroll;
3172         GtkWidget *new_button;
3173
3174         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3175                                               GTK_WINDOW (win),
3176                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3177                                               NULL);
3178
3179         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
3180         /* We do this manually so GTK+ does not associate a response ID for
3181          * the button. */
3182         new_button = gtk_button_new_from_stock (GTK_STOCK_NEW);
3183         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3184         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
3185
3186         /* Create scrolled window */
3187         scroll = gtk_scrolled_window_new (NULL, NULL);
3188         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3189                                          GTK_POLICY_AUTOMATIC,
3190                                          GTK_POLICY_AUTOMATIC);
3191
3192         /* Create folder view */
3193         *tree_view = modest_platform_create_folder_view (NULL);
3194
3195         g_signal_connect (G_OBJECT (new_button), "clicked", G_CALLBACK(create_move_to_dialog_on_new_folder), *tree_view);
3196
3197         /* It could happen that we're trying to move a message from a
3198            window (msg window for example) after the main window was
3199            closed, so we can not just get the model of the folder
3200            view */
3201         if (MODEST_IS_FOLDER_VIEW (folder_view))
3202                 gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
3203                                          gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
3204         else
3205                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3206                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3207
3208         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3209         
3210         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3211
3212         /* Add scroll to dialog */
3213         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3214                             scroll, TRUE, TRUE, 0);
3215
3216         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3217         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3218
3219         return dialog;
3220 }
3221
3222 /*
3223  * Returns TRUE if at least one of the headers of the list belongs to
3224  * a message that has been fully retrieved.
3225  */
3226 static gboolean
3227 has_retrieved_msgs (TnyList *list)
3228 {
3229         TnyIterator *iter;
3230         gboolean found = FALSE;
3231
3232         iter = tny_list_create_iterator (list);
3233         while (tny_iterator_is_done (iter) && !found) {
3234                 TnyHeader *header;
3235                 TnyHeaderFlags flags;
3236
3237                 header = TNY_HEADER (tny_iterator_get_current (iter));
3238                 flags = tny_header_get_flags (header);
3239                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
3240                         found = TRUE;
3241
3242                 if (!found)
3243                         tny_iterator_next (iter);
3244         }
3245         g_object_unref (iter);
3246
3247         return found;
3248 }
3249
3250 /*
3251  * Shows a confirmation dialog to the user when we're moving messages
3252  * from a remote server to the local storage. Returns the dialog
3253  * response. If it's other kind of movement the it always returns
3254  * GTK_RESPONSE_OK
3255  */
3256 static gint
3257 msgs_move_to_confirmation (GtkWindow *win,
3258                            TnyFolder *dest_folder,
3259                            TnyList *headers)
3260 {
3261         gint response = GTK_RESPONSE_OK;
3262
3263         /* If the destination is a local folder */
3264         if (modest_tny_folder_is_local_folder (dest_folder)) {
3265                 TnyFolder *src_folder;
3266                 TnyIterator *iter;
3267                 TnyHeader *header;
3268
3269                 /* Get source folder */
3270                 iter = tny_list_create_iterator (headers);
3271                 header = TNY_HEADER (tny_iterator_get_current (iter));
3272                 src_folder = tny_header_get_folder (header);
3273                 g_object_unref (header);
3274                 g_object_unref (iter);
3275
3276                 /* if no src_folder, message may be an attahcment */
3277                 if (src_folder == NULL) 
3278                         return GTK_RESPONSE_CANCEL;
3279
3280                 /* If the source is a remote folder */
3281                 if (!modest_tny_folder_is_local_folder (src_folder)) {
3282                         const gchar *message;
3283                         
3284                         if (has_retrieved_msgs (headers))
3285                                 message = ngettext ("mcen_nc_move_retrieve", "mcen_nc_move_retrieves",
3286                                                     tny_list_get_length (headers));
3287                         else 
3288                                 message = ngettext ("mcen_nc_move_header", "mcen_nc_move_headers",
3289                                                     tny_list_get_length (headers));
3290
3291                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
3292                                                                             (const gchar *) message);
3293                 }
3294                 g_object_unref (src_folder);
3295         }
3296         return response;
3297 }
3298
3299
3300
3301 static void
3302 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3303 {
3304         ModestMsgViewWindow *self = NULL;
3305
3306         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3307         self = MODEST_MSG_VIEW_WINDOW (object);
3308         
3309         if (!modest_msg_view_window_select_next_message (self))
3310                 if (!modest_msg_view_window_select_previous_message (self))
3311                         /* No more messages to view, so close this window */
3312                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3313 }
3314
3315 void
3316 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3317                                              gpointer user_data)
3318 {
3319         GObject *win = modest_mail_operation_get_source (mail_op);
3320         const GError *error = NULL;
3321         const gchar *message = NULL;
3322         
3323         /* Get error message */
3324         error = modest_mail_operation_get_error (mail_op);
3325         if (error != NULL && error->message != NULL) {
3326                 message = error->message;
3327         } else {
3328                 message = _("mail_in_ui_folder_move_target_error");
3329         }
3330         
3331         /* Show notification dialog */
3332         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3333         g_object_unref (win);
3334 }
3335
3336 void
3337 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3338                                               gpointer user_data)
3339 {
3340         GObject *win = modest_mail_operation_get_source (mail_op);
3341         const GError *error = modest_mail_operation_get_error (mail_op);
3342
3343         g_return_if_fail (error != NULL);
3344         if (error->message != NULL)             
3345                 g_printerr ("modest: %s\n", error->message);
3346         else
3347                 g_printerr ("modest: unkonw error on send&receive operation");
3348
3349         /* Show error message */
3350 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3351 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3352 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3353 /*      else  */
3354 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3355 /*                                                      _CS("sfil_ib_unable_to_send")); */
3356         g_object_unref (win);
3357 }
3358
3359 static void
3360 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3361                        TnyHeader *header, 
3362                        TnyMsg *msg, 
3363                        gpointer user_data)
3364 {
3365         TnyList *parts;
3366         TnyIterator *iter;
3367         gint pending_purges = 0;
3368         gboolean some_purged = FALSE;
3369         ModestWindow *win = MODEST_WINDOW (user_data);
3370         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3371
3372         /* If there was any error */
3373         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
3374                 modest_window_mgr_unregister_header (mgr, header);
3375                 return;
3376         }
3377
3378         /* Once the message has been retrieved for purging, we check if
3379          * it's all ok for purging */
3380
3381         parts = tny_simple_list_new ();
3382         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3383         iter = tny_list_create_iterator (parts);
3384
3385         while (!tny_iterator_is_done (iter)) {
3386                 TnyMimePart *part;
3387                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3388                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)) {
3389                         if (tny_mime_part_is_purged (part))
3390                                 some_purged = TRUE;
3391                         else
3392                                 pending_purges++;
3393                 }
3394                 tny_iterator_next (iter);
3395         }
3396
3397         if (pending_purges>0) {
3398                 gint response;
3399                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3400
3401                 if (response == GTK_RESPONSE_OK) {
3402                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3403                         tny_iterator_first (iter);
3404                         while (!tny_iterator_is_done (iter)) {
3405                                 TnyMimePart *part;
3406                                 
3407                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3408                                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))
3409                                         tny_mime_part_set_purged (part);
3410                                 tny_iterator_next (iter);
3411                         }
3412                         
3413                         tny_msg_rewrite_cache (msg);
3414                 }
3415         } else {
3416                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3417         }
3418
3419         /* remove attachments */
3420         tny_iterator_first (iter);
3421         while (!tny_iterator_is_done (iter)) {
3422                 TnyMimePart *part;
3423                         
3424                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3425                 g_object_unref (part);
3426                 tny_iterator_next (iter);
3427         }
3428         modest_window_mgr_unregister_header (mgr, header);
3429
3430         g_object_unref (iter);
3431         g_object_unref (parts);
3432 }
3433
3434 static void
3435 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3436                                                      ModestMainWindow *win)
3437 {
3438         GtkWidget *header_view;
3439         TnyList *header_list;
3440         TnyIterator *iter;
3441         TnyHeader *header;
3442         TnyHeaderFlags flags;
3443         ModestWindow *msg_view_window =  NULL;
3444         gboolean found;
3445
3446         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3447
3448         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3449                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3450
3451         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3452
3453         if (tny_list_get_length (header_list) == 1) {
3454                 iter = tny_list_create_iterator (header_list);
3455                 header = TNY_HEADER (tny_iterator_get_current (iter));
3456                 g_object_unref (iter);
3457         } else {
3458                 return;
3459         }
3460
3461         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3462                                                           header, &msg_view_window);
3463         flags = tny_header_get_flags (header);
3464         if (!(flags & TNY_HEADER_FLAG_CACHED))
3465                 return;
3466         if (found) {
3467                 if (msg_view_window != NULL) 
3468                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3469                 else {
3470                         /* do nothing; uid was registered before, so window is probably on it's way */
3471                         g_warning ("debug: header %p has already been registered", header);
3472                 }
3473         } else {
3474                 ModestMailOperation *mail_op = NULL;
3475                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3476                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3477                                                                          G_OBJECT (win),
3478                                                                          modest_ui_actions_get_msgs_full_error_handler,
3479                                                                          NULL);
3480                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3481                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3482                 
3483                 g_object_unref (mail_op);
3484         }
3485         if (header)
3486                 g_object_unref (header);
3487         if (header_list)
3488                 g_object_unref (header_list);
3489 }
3490
3491 /**
3492  * Utility function that transfer messages from both the main window
3493  * and the msg view window when using the "Move to" dialog
3494  */
3495 static void
3496 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
3497                                               ModestWindow *win)
3498 {
3499         TnyList *headers = NULL;
3500         gint response = 0;
3501
3502         if (!TNY_IS_FOLDER (dst_folder)) {
3503                 modest_platform_information_banner (GTK_WIDGET (win),
3504                                                     NULL,
3505                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
3506                 return;
3507         }
3508
3509         /* Get selected headers */
3510         headers = get_selected_headers (MODEST_WINDOW (win));
3511
3512         /* Ask for user confirmation */
3513         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3514                                               TNY_FOLDER (dst_folder), 
3515                                               headers);
3516
3517         /* Transfer messages */
3518         if (response == GTK_RESPONSE_OK) {
3519                 ModestMailOperation *mail_op = 
3520                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3521                                                                        G_OBJECT(win),
3522                                                                        modest_ui_actions_move_folder_error_handler,
3523                                                                        NULL);
3524                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3525                                                  mail_op);
3526
3527                 modest_mail_operation_xfer_msgs (mail_op, 
3528                                                  headers,
3529                                                  TNY_FOLDER (dst_folder),
3530                                                  TRUE,
3531                                                  (MODEST_IS_MSG_VIEW_WINDOW (win)) ? transfer_msgs_from_viewer_cb : NULL,
3532                                                  NULL);
3533
3534                 g_object_unref (G_OBJECT (mail_op));
3535         }
3536         g_object_unref (headers);
3537 }
3538
3539
3540 /*
3541  * UI handler for the "Move to" action when invoked from the
3542  * ModestMainWindow
3543  */
3544 static void 
3545 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
3546                                           GtkWidget *folder_view,
3547                                           TnyFolderStore *dst_folder,
3548                                           ModestMainWindow *win)
3549 {
3550         GtkWidget *header_view = NULL;
3551         ModestMailOperation *mail_op = NULL;
3552         TnyFolderStore *src_folder;
3553
3554         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3555
3556         /* Get the source folder */
3557         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3558         
3559         /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
3560         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
3561                                                                       src_folder))
3562                 goto end;
3563
3564         /* Get header view */
3565         header_view = 
3566                 modest_main_window_get_child_widget (win, MODEST_WIDGET_TYPE_HEADER_VIEW);
3567
3568         /* Get folder or messages to transfer */
3569         if (gtk_widget_is_focus (folder_view)) {
3570
3571                 /* Allow only to transfer folders to the local root folder */
3572                 if (TNY_IS_ACCOUNT (dst_folder) && 
3573                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder))
3574                         goto end;
3575                 
3576                 /* Clean folder on header view before moving it */
3577                 modest_header_view_clear (MODEST_HEADER_VIEW (header_view)); 
3578
3579                 if (TNY_IS_FOLDER (src_folder)) {
3580                         mail_op = 
3581                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3582                                                                                G_OBJECT(win),
3583                                                                                modest_ui_actions_move_folder_error_handler,
3584                                                                                NULL);
3585                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3586                                                          mail_op);
3587
3588                         modest_mail_operation_xfer_folder (mail_op, 
3589                                                            TNY_FOLDER (src_folder),
3590                                                            dst_folder,
3591                                                            TRUE, NULL, NULL);
3592                         /* Unref mail operation */
3593                         g_object_unref (G_OBJECT (mail_op));
3594                 } else {
3595                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);       
3596                 }
3597         } else if (gtk_widget_is_focus (header_view)) {
3598                 /* Transfer messages */
3599                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3600         }
3601         
3602  end:
3603     if (src_folder)
3604         g_object_unref (src_folder);
3605 }
3606
3607
3608 /*
3609  * UI handler for the "Move to" action when invoked from the
3610  * ModestMsgViewWindow
3611  */
3612 static void 
3613 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
3614                                               TnyFolderStore *dst_folder,
3615                                               ModestMsgViewWindow *win)
3616 {
3617         TnyHeader *header = NULL;
3618         TnyFolder *src_folder;
3619
3620         /* Create header list */
3621         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
3622         src_folder = tny_header_get_folder(header);
3623         g_object_unref (header);
3624
3625         /* Transfer the message */
3626         if (modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (src_folder)))
3627                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3628
3629         g_object_unref (src_folder);
3630 }
3631
3632 void 
3633 modest_ui_actions_on_move_to (GtkAction *action, 
3634                               ModestWindow *win)
3635 {
3636         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
3637         gint result = 0;
3638         TnyFolderStore *dst_folder = NULL;
3639         ModestMainWindow *main_window;
3640
3641         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
3642                           MODEST_IS_MSG_VIEW_WINDOW (win));
3643
3644         /* Get the main window if exists */
3645         if (MODEST_IS_MAIN_WINDOW (win))
3646                 main_window = MODEST_MAIN_WINDOW (win);
3647         else
3648                 main_window = 
3649                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
3650
3651         /* Get the folder view widget if exists */
3652         if (main_window)
3653                 folder_view = modest_main_window_get_child_widget (main_window,
3654                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
3655         else
3656                 folder_view = NULL;
3657
3658         /* Create and run the dialog */
3659         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
3660         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
3661         result = gtk_dialog_run (GTK_DIALOG(dialog));
3662         g_object_ref (tree_view);
3663         gtk_widget_destroy (dialog);
3664
3665         if (result != GTK_RESPONSE_ACCEPT)
3666                 return;
3667
3668         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
3669         /* Offer the connection dialog if necessary: */
3670         if (modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
3671                                                                       dst_folder)) {
3672
3673                 /* Do window specific stuff */
3674                 if (MODEST_IS_MAIN_WINDOW (win))
3675                         modest_ui_actions_on_main_window_move_to (action,
3676                                                                   folder_view,
3677                                                                   dst_folder,
3678                                                                   MODEST_MAIN_WINDOW (win));
3679                 else
3680                         modest_ui_actions_on_msg_view_window_move_to (action,
3681                                                                       dst_folder,
3682                                                                       MODEST_MSG_VIEW_WINDOW (win));
3683         }
3684         if (dst_folder)
3685                 g_object_unref (dst_folder);
3686 }
3687
3688 /*
3689  * Calls #HeadersFunc for each header already selected in the main
3690  * window or the message currently being shown in the msg view window
3691  */
3692 static void
3693 do_headers_action (ModestWindow *win, 
3694                    HeadersFunc func,
3695                    gpointer user_data)
3696 {
3697         TnyList *headers_list;
3698         TnyIterator *iter;
3699         TnyHeader *header;
3700         TnyFolder *folder;
3701
3702         /* Get headers */
3703         headers_list = get_selected_headers (win);
3704         if (!headers_list)
3705                 return;
3706
3707         /* Get the folder */
3708         iter = tny_list_create_iterator (headers_list);
3709         header = TNY_HEADER (tny_iterator_get_current (iter));
3710         folder = tny_header_get_folder (header);
3711         g_object_unref (header);
3712
3713         /* Call the function for each header */
3714         while (!tny_iterator_is_done (iter)) {
3715                 header = TNY_HEADER (tny_iterator_get_current (iter));
3716                 func (header, win, user_data);
3717                 g_object_unref (header);
3718                 tny_iterator_next (iter);
3719         }
3720
3721         /* Trick: do a poke status in order to speed up the signaling
3722            of observers */
3723         tny_folder_poke_status (folder);
3724
3725         /* Frees */
3726         g_object_unref (folder);
3727         g_object_unref (iter);
3728         g_object_unref (headers_list);
3729 }
3730
3731 void 
3732 modest_ui_actions_view_attachment (GtkAction *action,
3733                                    ModestWindow *window)
3734 {
3735         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3736                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
3737         } else {
3738                 /* not supported window for this action */
3739                 g_return_if_reached ();
3740         }
3741 }
3742
3743 void
3744 modest_ui_actions_save_attachments (GtkAction *action,
3745                                     ModestWindow *window)
3746 {
3747         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3748                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
3749         } else {
3750                 /* not supported window for this action */
3751                 g_return_if_reached ();
3752         }
3753 }
3754
3755 void
3756 modest_ui_actions_remove_attachments (GtkAction *action,
3757                                       ModestWindow *window)
3758 {
3759         if (MODEST_IS_MAIN_WINDOW (window)) {
3760                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
3761         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3762                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
3763         } else {
3764                 /* not supported window for this action */
3765                 g_return_if_reached ();
3766         }
3767 }
3768
3769 void 
3770 modest_ui_actions_on_settings (GtkAction *action, 
3771                                ModestWindow *win)
3772 {
3773         GtkWidget *dialog;
3774
3775         dialog = modest_platform_get_global_settings_dialog ();
3776         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
3777         gtk_widget_show_all (dialog);
3778
3779         gtk_dialog_run (GTK_DIALOG (dialog));
3780
3781         gtk_widget_destroy (dialog);
3782 }
3783
3784 void 
3785 modest_ui_actions_on_help (GtkAction *action, 
3786                            ModestWindow *win)
3787 {
3788         const gchar *help_id = NULL;
3789
3790         if (MODEST_IS_MAIN_WINDOW (win)) {
3791                 const gchar *action_name;
3792                 action_name = gtk_action_get_name (action);
3793
3794                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
3795                     !strcmp (action_name, "HeaderViewCSMHelp")) {
3796                         GtkWidget *folder_view;
3797                         TnyFolderStore *folder_store;
3798                         /* Get selected folder */
3799                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3800                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3801                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3802
3803                         /* Switch help_id */
3804                         if (TNY_IS_FOLDER (folder_store)) {
3805                                 switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
3806                                 case TNY_FOLDER_TYPE_NORMAL:
3807                                         help_id = "applications_email_managefolders";
3808                                         break;
3809                                 case TNY_FOLDER_TYPE_INBOX:
3810                                         help_id = "applications_email_inbox";
3811                                         break;
3812                                 case TNY_FOLDER_TYPE_OUTBOX:
3813                                         help_id = "applications_email_outbox";
3814                                         break;
3815                                 case TNY_FOLDER_TYPE_SENT:
3816                                         help_id = "applications_email_sent";
3817                                         break;
3818                                 case TNY_FOLDER_TYPE_DRAFTS:
3819                                         help_id = "applications_email_drafts";
3820                                         break;
3821                                 case TNY_FOLDER_TYPE_ARCHIVE:
3822                                         help_id = "applications_email_managefolders";
3823                                         break;
3824                                 default:
3825                                         help_id = "applications_email_managefolders";
3826                                 }
3827                         } else {
3828                                 help_id = "applications_email_mainview";        
3829                         }
3830                         g_object_unref (folder_store);
3831                 } else {
3832                         help_id = "applications_email_mainview";        
3833                 }
3834         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3835                 help_id = "applications_email_viewer";
3836         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
3837                 help_id = "applications_email_editor";
3838
3839         modest_platform_show_help (GTK_WINDOW (win), help_id);
3840 }
3841
3842 void 
3843 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
3844                                             ModestWindow *window)
3845 {
3846         ModestMailOperation *mail_op;
3847         TnyList *headers;
3848
3849         /* Get headers */
3850         headers = get_selected_headers (window);
3851         if (!headers)
3852                 return;
3853
3854         /* Create mail operation */
3855         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3856                                                                  G_OBJECT (window),
3857                                                                  modest_ui_actions_get_msgs_full_error_handler, 
3858                                                                  NULL);
3859         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3860         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
3861
3862         /* Frees */
3863         g_object_unref (headers);
3864         g_object_unref (mail_op);
3865 }
3866
3867 void
3868 modest_ui_actions_on_email_menu_activated (GtkAction *action,
3869                                           ModestWindow *window)
3870 {
3871         g_return_if_fail (MODEST_IS_WINDOW (window));
3872
3873         /* Update dimmed */     
3874         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3875 }
3876
3877 void
3878 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
3879                                           ModestWindow *window)
3880 {
3881         g_return_if_fail (MODEST_IS_WINDOW (window));
3882
3883         /* Update dimmed */     
3884         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3885 }
3886
3887 void
3888 modest_ui_actions_on_view_menu_activated (GtkAction *action,
3889                                           ModestWindow *window)
3890 {
3891         g_return_if_fail (MODEST_IS_WINDOW (window));
3892
3893         /* Update dimmed */     
3894         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3895 }
3896
3897 void
3898 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
3899                                           ModestWindow *window)
3900 {
3901         g_return_if_fail (MODEST_IS_WINDOW (window));
3902
3903         /* Update dimmed */     
3904         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3905 }
3906
3907 void
3908 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
3909                                           ModestWindow *window)
3910 {
3911         g_return_if_fail (MODEST_IS_WINDOW (window));
3912
3913         /* Update dimmed */     
3914         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3915 }
3916
3917 void
3918 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
3919                                                  ModestWindow *window)
3920 {
3921         g_return_if_fail (MODEST_IS_WINDOW (window));
3922
3923         /* Update dimmed */     
3924         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3925 }
3926
3927 void
3928 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
3929                                                      ModestWindow *window)
3930 {
3931         g_return_if_fail (MODEST_IS_WINDOW (window));
3932
3933         /* Update dimmed */     
3934         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3935 }
3936
3937 void
3938 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
3939                                                      ModestWindow *window)
3940 {
3941         g_return_if_fail (MODEST_IS_WINDOW (window));
3942
3943         /* Update dimmed */     
3944         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3945 }
3946
3947 void
3948 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3949 {
3950         g_return_if_fail (MODEST_IS_WINDOW (window));
3951
3952         /* Update dimmed */     
3953         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
3954 }
3955
3956 void
3957 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
3958 {
3959         g_return_if_fail (MODEST_IS_WINDOW (window));
3960
3961         modest_platform_show_search_messages (GTK_WINDOW (window));
3962 }
3963
3964 void     
3965 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
3966 {
3967         g_return_if_fail (MODEST_IS_WINDOW (win));
3968         modest_platform_show_addressbook (GTK_WINDOW (win));
3969 }
3970
3971
3972 void
3973 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
3974                                           ModestWindow *window)
3975 {
3976         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3977
3978         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
3979 }
3980
3981 static void 
3982 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
3983                                    ModestMailOperationState *state,
3984                                    gpointer user_data)
3985 {
3986         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
3987
3988         /* Set send/receive operation finished */       
3989         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3990                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
3991         
3992 }
3993
3994