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