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