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