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