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