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