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