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