348b2b871488e6988ae11e09528bb8c684b3f170
[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 <string.h>
36 #include <modest-runtime.h>
37 #include <modest-tny-folder.h>
38 #include <modest-tny-msg.h>
39 #include <modest-tny-account.h>
40 #include <modest-address-book.h>
41
42 #include "modest-ui-actions.h"
43
44 #include "modest-tny-platform-factory.h"
45 #include "modest-platform.h"
46
47 #ifdef MODEST_PLATFORM_MAEMO
48 #include "maemo/modest-osso-state-saving.h"
49 #endif /* MODEST_PLATFORM_MAEMO */
50
51 #include "widgets/modest-ui-constants.h"
52 #include <widgets/modest-main-window.h>
53 #include <widgets/modest-msg-view-window.h>
54 #include <widgets/modest-account-view-window.h>
55 #include <widgets/modest-details-dialog.h>
56 #include <widgets/modest-attachments-view.h>
57 #include "widgets/modest-global-settings-dialog.h"
58 #include "modest-connection-specific-smtp-window.h"
59 #include "modest-account-mgr-helpers.h"
60 #include "modest-mail-operation.h"
61 #include "modest-text-utils.h"
62
63 #ifdef MODEST_HAVE_EASYSETUP
64 #include "easysetup/modest-easysetup-wizard.h"
65 #endif /* MODEST_HAVE_EASYSETUP */
66
67 #include <modest-widget-memory.h>
68 #include <tny-error.h>
69 #include <tny-simple-list.h>
70 #include <tny-msg-view.h>
71 #include <tny-device.h>
72 #include <tny-merge-folder.h>
73
74 typedef struct _GetMsgAsyncHelper {     
75         ModestWindow *window;
76         ModestMailOperation *mail_op;
77         TnyIterator *iter;
78         guint num_ops;
79         GFunc func;     
80         gpointer user_data;
81 } GetMsgAsyncHelper;
82
83 typedef enum _ReplyForwardAction {
84         ACTION_REPLY,
85         ACTION_REPLY_TO_ALL,
86         ACTION_FORWARD
87 } ReplyForwardAction;
88
89 typedef struct _ReplyForwardHelper {
90         guint reply_forward_type;
91         ReplyForwardAction action;
92         gchar *account_name;
93 } ReplyForwardHelper;
94
95 /*
96  * The do_headers_action uses this kind of functions to perform some
97  * action to each member of a list of headers
98  */
99 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
100
101 static void
102 do_headers_action (ModestWindow *win, 
103                    HeadersFunc func,
104                    gpointer user_data);
105
106
107 static void     open_msg_cb            (ModestMailOperation *mail_op, 
108                                         TnyHeader *header, 
109                                         TnyMsg *msg,
110                                         gpointer user_data);
111
112 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
113                                         TnyHeader *header, 
114                                         TnyMsg *msg,
115                                         gpointer user_data);
116
117 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
118
119 static gchar*   ask_for_folder_name    (GtkWindow *parent_window, const gchar *title);
120
121 void   
122 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
123 {
124         GtkWidget *about;
125         const gchar *authors[] = {
126                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
127                 NULL
128         };
129         about = gtk_about_dialog_new ();
130         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
131         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
132         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
133                                         _("Copyright (c) 2006, Nokia Corporation\n"
134                                           "All rights reserved."));
135         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
136                                        _("a modest e-mail client\n\n"
137                                          "design and implementation: Dirk-Jan C. Binnema\n"
138                                          "contributions from the fine people at KC and Ig\n"
139                                          "uses the tinymail email framework written by Philip van Hoof"));
140         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
141         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
142         
143         gtk_dialog_run (GTK_DIALOG (about));
144         gtk_widget_destroy(about);
145 }
146
147 /*
148  * Gets the list of currently selected messages. If the win is the
149  * main window, then it returns a newly allocated list of the headers
150  * selected in the header view. If win is the msg view window, then
151  * the value returned is a list with just a single header.
152  *
153  * The caller of this funcion must free the list.
154  */
155 static TnyList *
156 get_selected_headers (ModestWindow *win)
157 {
158         if (MODEST_IS_MAIN_WINDOW(win)) {
159                 GtkWidget *header_view;         
160                 
161                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
162                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
163                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
164                 
165         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
166                 /* for MsgViewWindows, we simply return a list with one element */
167                 TnyHeader *header;
168                 TnyList *list = NULL;
169                 
170                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
171                 if (header != NULL) {
172                         list = tny_simple_list_new ();
173                         tny_list_prepend (list, G_OBJECT(header));
174                         g_object_unref (G_OBJECT(header));
175                 }
176
177                 return list;
178
179         } else
180                 return NULL;
181 }
182
183 static void
184 headers_action_mark_as_read (TnyHeader *header,
185                              ModestWindow *win,
186                              gpointer user_data)
187 {
188         TnyHeaderFlags flags;
189
190         g_return_if_fail (TNY_IS_HEADER(header));
191
192         flags = tny_header_get_flags (header);
193         if (flags & TNY_HEADER_FLAG_SEEN) return;
194         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
195 }
196
197 static void
198 headers_action_mark_as_unread (TnyHeader *header,
199                                ModestWindow *win,
200                                gpointer user_data)
201 {
202         TnyHeaderFlags flags;
203
204         g_return_if_fail (TNY_IS_HEADER(header));
205
206         flags = tny_header_get_flags (header);
207         if (flags & TNY_HEADER_FLAG_SEEN)  {
208                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
209         }
210 }
211
212
213 static void
214 headers_action_delete (TnyHeader *header,
215                        ModestWindow *win,
216                        gpointer user_data)
217 {
218         ModestMailOperation *mail_op = NULL;
219
220         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, G_OBJECT(win));
221         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
222                                          mail_op);
223         
224         /* Always delete. TODO: Move to trash still not supported */
225         modest_mail_operation_remove_msg (mail_op, header, FALSE);
226         g_object_unref (G_OBJECT (mail_op));
227 }
228
229 void
230 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
231 {
232         TnyList *header_list = NULL;
233         TnyIterator *iter = NULL;
234         TnyHeader *header = NULL;
235         gchar *message = NULL;
236         gchar *desc = NULL;
237         gint response;
238
239         g_return_if_fail (MODEST_IS_WINDOW(win));
240
241         header_list = get_selected_headers (win);
242         if (!header_list) return;
243
244         /* Select message */
245         if (tny_list_get_length(header_list) > 1)
246                 message = g_strdup(_("emev_nc_delete_messages"));
247         else {
248                 iter = tny_list_create_iterator (header_list);
249                 header = TNY_HEADER (tny_iterator_get_current (iter));
250                 desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
251                 message = g_strdup_printf(_("emev_nc_delete_message"), desc);
252         }
253
254         /* Confirmation dialog */               
255         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
256                                                             message);
257         
258
259         if (response == GTK_RESPONSE_OK) {
260                 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
261                         gboolean ret_value;
262                         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
263                         return;
264                 }
265                 
266                 /* Remove each header */
267                 do_headers_action (win, headers_action_delete, NULL);
268
269                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
270                         gtk_widget_destroy (GTK_WIDGET(win));
271                 } 
272         }
273
274         /* free */
275         g_free(message);
276         g_free(desc);
277         g_object_unref (header_list);
278         g_object_unref (iter);
279 }
280
281
282 void
283 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
284 {
285         #ifdef MODEST_PLATFORM_MAEMO
286         modest_osso_save_state();
287         #endif /* MODEST_PLATFORM_MAEMO */
288         
289         gtk_main_quit ();
290 }
291
292 void
293 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
294 {
295         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
296                 gtk_widget_destroy (GTK_WIDGET (win));
297         } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
298                 gboolean ret_value;
299                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
300         } else if (MODEST_IS_WINDOW (win)) {
301                 gtk_widget_destroy (GTK_WIDGET (win));
302         } else {
303                 g_return_if_reached ();
304         }
305 }
306
307 void
308 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
309 {
310         GtkClipboard *clipboard = NULL;
311         gchar *selection = NULL;
312
313         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
314         selection = gtk_clipboard_wait_for_text (clipboard);
315
316         modest_address_book_add_address (selection);
317         g_free (selection);
318 }
319
320 void
321 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
322 {
323         /* This is currently only implemented for Maemo,
324          * because it requires a providers preset file which is not publically available.
325          */
326 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
327         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
328                                 TRUE /* enabled accounts only */);
329         gboolean accounts_exist = account_names != NULL;
330         g_slist_free (account_names);
331         
332         if (!accounts_exist) {
333                 /* If there are no accounts yet, just show the easy-setup wizard, as per the UI spec: */
334                 ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new ();
335                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
336                 gtk_dialog_run (GTK_DIALOG (wizard));
337                 gtk_widget_destroy (GTK_WIDGET (wizard));
338         } else  {
339                 /* Show the list of accounts: */
340                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
341                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
342                 gtk_dialog_run (account_win);
343                 gtk_widget_destroy (GTK_WIDGET(account_win));
344         }
345 #else
346         GtkWidget *dialog, *label;
347         
348         /* Create the widgets */
349         
350         dialog = gtk_dialog_new_with_buttons ("Message",
351                                               GTK_WINDOW(win),
352                                               GTK_DIALOG_DESTROY_WITH_PARENT,
353                                               GTK_STOCK_OK,
354                                               GTK_RESPONSE_NONE,
355                                               NULL);
356         label = gtk_label_new ("Hello World!");
357         
358         /* Ensure that the dialog box is destroyed when the user responds. */
359         
360         g_signal_connect_swapped (dialog, "response", 
361                                   G_CALLBACK (gtk_widget_destroy),
362                                   dialog);
363         
364         /* Add the label, and show everything we've added to the dialog. */
365         
366         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
367                            label);
368         gtk_widget_show_all (dialog);
369 #endif /* MODEST_PLATFORM_MAEMO */
370 }
371
372 static void
373 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
374 {
375         ModestWindow *main_window = MODEST_WINDOW (user_data);
376         
377         /* Save any changes. */
378         modest_connection_specific_smtp_window_save_server_accounts (
379                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window), 
380                         modest_window_get_active_account (main_window));
381         gtk_widget_destroy (GTK_WIDGET (window));
382 }
383
384 void
385 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
386 {
387         /* This is currently only implemented for Maemo,
388          * because it requires an API (libconic) to detect different connection 
389          * possiblities.
390          */
391 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
392         
393         /* Create the window if necessary: */
394         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
395         modest_connection_specific_smtp_window_fill_with_connections (
396                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
397                 modest_runtime_get_account_mgr(), 
398                 modest_window_get_active_account (win));
399
400         /* Show the window: */  
401         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
402         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
403     gtk_widget_show (specific_window);
404     
405     /* Save changes when the window is hidden: */
406         g_signal_connect (specific_window, "hide", 
407                 G_CALLBACK (on_smtp_servers_window_hide), win);
408 #endif /* MODEST_PLATFORM_MAEMO */
409 }
410
411 void
412 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
413 {
414         ModestWindow *msg_win;
415         TnyMsg *msg = NULL;
416         TnyFolder *folder = NULL;
417         gchar *account_name = NULL;
418         gchar *from_str = NULL;
419 /*      GError *err = NULL; */
420         TnyAccount *account = NULL;
421         ModestWindowMgr *mgr;
422         gchar *signature = NULL;
423         
424         account_name = g_strdup(modest_window_get_active_account (win));
425         if (!account_name)
426                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
427         if (!account_name) {
428                 g_printerr ("modest: no account found\n");
429                 goto cleanup;
430         }
431         
432         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
433                                                                        account_name,
434                                                                        TNY_ACCOUNT_TYPE_STORE);
435         if (!account) {
436                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
437                 goto cleanup;
438         }
439
440         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
441         if (!from_str) {
442                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
443                 goto cleanup;
444         }
445
446         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr (), account_name,
447                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
448                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), account_name,
449                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
450         } else {
451                 signature = g_strdup ("");
452         }
453
454         msg = modest_tny_msg_new ("", from_str, "", "", "", signature, NULL);
455         if (!msg) {
456                 g_printerr ("modest: failed to create new msg\n");
457                 goto cleanup;
458         }
459         
460         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
461         if (!folder) {
462                 g_printerr ("modest: failed to find Drafts folder\n");
463                 goto cleanup;
464         }
465         
466 /*      tny_folder_add_msg (folder, msg, &err); */
467 /*      if (err) { */
468 /*              g_printerr ("modest: error adding msg to Drafts folder: %s", */
469 /*                          err->message); */
470 /*              g_error_free (err); */
471 /*              goto cleanup; */
472 /*      } */
473
474         /* Create and register edit window */
475         /* This is destroyed by TOOD. */
476         msg_win = modest_msg_edit_window_new (msg, account_name);
477         mgr = modest_runtime_get_window_mgr ();
478         modest_window_mgr_register_window (mgr, msg_win);
479
480         if (win)
481                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
482                                               GTK_WINDOW (win));        
483         gtk_widget_show_all (GTK_WIDGET (msg_win));
484
485 cleanup:
486         g_free (account_name);
487         g_free (from_str);
488         g_free (signature);
489         if (account)
490                 g_object_unref (G_OBJECT(account));
491         if (msg)
492                 g_object_unref (G_OBJECT(msg));
493         if (folder)
494                 g_object_unref (G_OBJECT(folder));
495 }
496
497 static void
498 open_msg_cb (ModestMailOperation *mail_op, 
499              TnyHeader *header, 
500              TnyMsg *msg, 
501              gpointer user_data)
502 {
503         ModestWindowMgr *mgr = NULL;
504         ModestWindow *parent_win = NULL;
505         ModestWindow *win = NULL;
506         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
507         gchar *account = NULL;
508         TnyFolder *folder;
509         
510         /* TODO: Show an error? (review the specs) */
511         if (!msg)
512                 return;
513
514         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
515         folder = tny_header_get_folder (header);
516
517         /* Mark header as read */
518         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
519
520         /* Get account */
521         account =  g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
522         if (!account)
523                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
524         
525         /* Gets folder type (OUTBOX headers will be opened in edit window */
526         if (modest_tny_folder_is_local_folder (folder))
527                 folder_type = modest_tny_folder_get_local_folder_type (folder);
528
529         /* If the header is in the drafts folder then open the editor,
530            else the message view window */
531         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
532                 win = modest_msg_edit_window_new (msg, account);
533         } else {
534                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
535                         GtkWidget *header_view;
536                         GtkTreeSelection *sel;
537                         GList *sel_list = NULL;
538                         GtkTreeModel *model;
539                 
540                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
541                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
542
543                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
544                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
545
546                         if (sel_list != NULL) {
547                                 GtkTreeRowReference *row_reference;
548
549                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
550                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
551                                 g_list_free (sel_list);
552                                 
553                                 win = modest_msg_view_window_new_with_header_model (msg, 
554                                                                                     account, 
555                                                                                     model, 
556                                                                                     row_reference);
557                                 gtk_tree_row_reference_free (row_reference);
558                         } else {
559                                 win = modest_msg_view_window_new (msg, account);
560                         }
561                 } else {
562                         win = modest_msg_view_window_new (msg, account);
563                 }
564         }
565         
566         /* Register and show new window */
567         if (win != NULL) {
568                 mgr = modest_runtime_get_window_mgr ();
569                 modest_window_mgr_register_window (mgr, win);
570                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
571                 gtk_widget_show_all (GTK_WIDGET(win));
572         }
573
574         /* Free */
575         g_free(account);
576         g_object_unref (msg);
577         g_object_unref (folder);
578         g_object_unref (header);
579 }
580
581 /*
582  * This function is used by both modest_ui_actions_on_open and
583  * modest_ui_actions_on_header_activated. This way we always do the
584  * same when trying to open messages.
585  */
586 static void
587 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
588 {
589         ModestWindowMgr *mgr;
590         TnyIterator *iter;
591         ModestMailOperation *mail_op;
592
593         /* Look if we already have a message view for each header. If
594            true, then remove the header from the list of headers to
595            open */
596         mgr = modest_runtime_get_window_mgr ();
597         iter = tny_list_create_iterator (headers);
598         while (!tny_iterator_is_done (iter)) {
599                 ModestWindow *window;
600                 TnyHeader *header;
601
602                 header = TNY_HEADER (tny_iterator_get_current (iter));
603                 window = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
604                 if (window)
605                         tny_list_remove (headers, G_OBJECT (header));
606
607                 g_object_unref (header);
608                 tny_iterator_next (iter);
609         }
610
611         /* Open each message */
612         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT (win));
613         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
614         modest_mail_operation_get_msgs_full (mail_op, 
615                                              headers, 
616                                              open_msg_cb, 
617                                              NULL, 
618                                              NULL);
619
620         /* Clean */
621         g_object_unref(mail_op);
622 }
623
624 void
625 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
626 {
627         TnyList *headers;
628
629         /* Get headers */
630         headers = get_selected_headers (win);
631         if (!headers)
632                 return;
633
634         /* Open them */
635         _modest_ui_actions_open (headers, win);
636
637         g_object_unref(headers);
638 }
639
640
641 static void
642 free_reply_forward_helper (gpointer data)
643 {
644         ReplyForwardHelper *helper;
645
646         helper = (ReplyForwardHelper *) data;
647         g_free (helper->account_name);
648         g_slice_free (ReplyForwardHelper, helper);
649 }
650
651 static void
652 reply_forward_cb (ModestMailOperation *mail_op, 
653                   TnyHeader *header, 
654                   TnyMsg *msg,
655                   gpointer user_data)
656 {
657         TnyMsg *new_msg;
658         ReplyForwardHelper *rf_helper;
659         ModestWindow *msg_win;
660         ModestEditType edit_type;
661         gchar *from;
662         GError *err = NULL;
663         TnyFolder *folder = NULL;
664         TnyAccount *account = NULL;
665         ModestWindowMgr *mgr;
666         gchar *signature = NULL;
667                         
668         g_return_if_fail (user_data != NULL);
669         rf_helper = (ReplyForwardHelper *) user_data;
670
671         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
672                                                    rf_helper->account_name);
673         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
674                                          rf_helper->account_name,
675                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
676                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
677                                                            rf_helper->account_name,
678                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
679         }
680
681         /* Create reply mail */
682         switch (rf_helper->action) {
683         case ACTION_REPLY:
684                 new_msg = 
685                         modest_tny_msg_create_reply_msg (msg,  from, signature,
686                                                          rf_helper->reply_forward_type,
687                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
688                 break;
689         case ACTION_REPLY_TO_ALL:
690                 new_msg = 
691                         modest_tny_msg_create_reply_msg (msg, from, signature, rf_helper->reply_forward_type,
692                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
693                 edit_type = MODEST_EDIT_TYPE_REPLY;
694                 break;
695         case ACTION_FORWARD:
696                 new_msg = 
697                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
698                 edit_type = MODEST_EDIT_TYPE_FORWARD;
699                 break;
700         default:
701                 g_return_if_reached ();
702                 return;
703         }
704
705         g_free (signature);
706
707         if (!new_msg) {
708                 g_printerr ("modest: failed to create message\n");
709                 goto cleanup;
710         }
711
712         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
713                                                                        rf_helper->account_name,
714                                                                        TNY_ACCOUNT_TYPE_STORE);
715         if (!account) {
716                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
717                 goto cleanup;
718         }
719
720         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
721         if (!folder) {
722                 g_printerr ("modest: failed to find Drafts folder\n");
723                 goto cleanup;
724         }
725         
726         tny_folder_add_msg (folder, msg, &err);
727         if (err) {
728                 g_printerr ("modest: error adding msg to Drafts folder: %s",
729                             err->message);
730                 g_error_free (err);
731                 goto cleanup;
732         }       
733
734         /* Create and register the windows */                   
735         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
736         mgr = modest_runtime_get_window_mgr ();
737         modest_window_mgr_register_window (mgr, msg_win);
738
739         /* Show edit window */
740         gtk_widget_show_all (GTK_WIDGET (msg_win));
741
742 cleanup:
743         if (new_msg)
744                 g_object_unref (G_OBJECT (new_msg));
745         if (folder)
746                 g_object_unref (G_OBJECT (folder));
747         if (account)
748                 g_object_unref (G_OBJECT (account));
749         g_object_unref (msg);
750         g_object_unref (header);
751 }
752
753 /*
754  * Checks a list of headers. If any of them are not currently
755  * downloaded (CACHED) then it asks the user for permission to
756  * download them.
757  *
758  * Returns FALSE if the user does not want to download the
759  * messages. Returns TRUE if the user allowed the download or if all
760  * of them are currently downloaded
761  */
762 static gboolean
763 download_uncached_messages (TnyList *header_list, GtkWindow *win)
764 {
765         TnyIterator *iter;
766         gboolean found, retval;
767
768         iter = tny_list_create_iterator (header_list);
769         found = FALSE;
770         while (!tny_iterator_is_done (iter) && !found) {
771                 TnyHeader *header;
772                 TnyHeaderFlags flags;
773
774                 header = TNY_HEADER (tny_iterator_get_current (iter));
775                 flags = tny_header_get_flags (header);
776                 found = !(flags & TNY_HEADER_FLAG_CACHED);
777                 g_object_unref (header);
778                 tny_iterator_next (iter);
779         }
780         g_object_unref (iter);
781
782         /* Ask for user permission to download the messages */
783         retval = TRUE;
784         if (found) {
785                 GtkResponseType response;
786                 response = 
787                         modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
788                                                                  _("mcen_nc_get_multi_msg_txt"));
789                 if (response == GTK_RESPONSE_CANCEL)
790                         retval = FALSE;
791         }
792         return retval;
793 }
794
795
796 /*
797  * Common code for the reply and forward actions
798  */
799 static void
800 reply_forward (ReplyForwardAction action, ModestWindow *win)
801 {
802         ModestMailOperation *mail_op = NULL;
803         TnyList *header_list = NULL;
804         ReplyForwardHelper *rf_helper = NULL;
805         guint reply_forward_type;
806         gboolean continue_download;
807         
808         g_return_if_fail (MODEST_IS_WINDOW(win));
809
810         header_list = get_selected_headers (win);
811         if (!header_list)
812                 return;
813
814         /* Check that the messages have been previously downloaded */
815         continue_download = download_uncached_messages (header_list, GTK_WINDOW (win));
816         if (!continue_download) {
817                 g_object_unref (header_list);
818                 return;
819         }
820         
821         reply_forward_type = 
822                 modest_conf_get_int (modest_runtime_get_conf (),
823                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
824                                      NULL);
825         /* We assume that we can only select messages of the
826            same folder and that we reply all of them from the
827            same account. In fact the interface currently only
828            allows single selection */
829         
830         /* Fill helpers */
831         rf_helper = g_slice_new0 (ReplyForwardHelper);
832         rf_helper->reply_forward_type = reply_forward_type;
833         rf_helper->action = action;
834         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
835         if (!rf_helper->account_name)
836                 rf_helper->account_name =
837                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
838
839         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
840                 TnyMsg *msg;
841                 TnyHeader *header;
842                 /* Get header and message. Do not free them here, the
843                    reply_forward_cb must do it */
844                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
845                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
846                 if (!msg || !header) {
847                         if (msg)
848                                 g_object_unref (msg);
849                         if (header)
850                                 g_object_unref (header);
851                         g_printerr ("modest: no message found\n");
852                         return;
853                 } else
854                         reply_forward_cb (NULL, header, msg, rf_helper);
855         } else {
856                 /* Retrieve messages */
857                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
858                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
859                 modest_mail_operation_get_msgs_full (mail_op, 
860                                                      header_list, 
861                                                      reply_forward_cb, 
862                                                      rf_helper, 
863                                                      free_reply_forward_helper);
864
865                 /* Clean */
866                 g_object_unref(mail_op);
867         }
868
869         /* Free */
870         g_object_unref (header_list);
871 }
872
873 void
874 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
875 {
876         g_return_if_fail (MODEST_IS_WINDOW(win));
877
878         reply_forward (ACTION_REPLY, win);
879 }
880
881 void
882 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
883 {
884         g_return_if_fail (MODEST_IS_WINDOW(win));
885
886         reply_forward (ACTION_FORWARD, win);
887 }
888
889 void
890 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
891 {
892         g_return_if_fail (MODEST_IS_WINDOW(win));
893
894         reply_forward (ACTION_REPLY_TO_ALL, win);
895 }
896
897 void 
898 modest_ui_actions_on_next (GtkAction *action, 
899                            ModestWindow *window)
900 {
901         if (MODEST_IS_MAIN_WINDOW (window)) {
902                 GtkWidget *header_view;
903
904                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
905                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
906                 if (!header_view)
907                         return;
908         
909                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
910         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
911                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
912         } else {
913                 g_return_if_reached ();
914         }
915 }
916
917 void 
918 modest_ui_actions_on_prev (GtkAction *action, 
919                            ModestWindow *window)
920 {
921         g_return_if_fail (MODEST_IS_WINDOW(window));
922
923         if (MODEST_IS_MAIN_WINDOW (window)) {
924                 GtkWidget *header_view;
925                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
926                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
927                 if (!header_view)
928                         return;
929                 
930                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
931         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
932                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
933         } else {
934                 g_return_if_reached ();
935         }
936 }
937
938 void 
939 modest_ui_actions_on_sort (GtkAction *action, 
940                            ModestWindow *window)
941 {
942         g_return_if_fail (MODEST_IS_WINDOW(window));
943
944         if (MODEST_IS_MAIN_WINDOW (window)) {
945                 GtkWidget *header_view;
946                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
947                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
948                 if (!header_view)
949                         return;
950
951                 /* Show sorting dialog */
952                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
953         }
954 }
955
956 /** Check that an appropriate connection is open.
957  */
958 gboolean check_for_connection (const gchar *account_name)
959 {
960         TnyDevice *device = modest_runtime_get_device ();
961
962 /*
963         g_assert (TNY_IS_MAEMO_CONIC_DEVICE (device));
964         
965         TnyMaemoConicDevice *maemo_device = TNY_MAEMO_CONIC_DEVICE (device);
966 */
967         
968         if (tny_device_is_online (device))
969                 return TRUE;
970         else {
971                 modest_platform_connect_and_wait (NULL);
972                 
973                 /* TODO: Wait until a result. */
974                 return TRUE;
975         }
976 }
977
978 /*
979  * This function performs the send & receive required actions. The
980  * window it's used to create the mail operation. Tipically it should
981  * be allways the main window, but we pass it as argument in order to
982  * be more flexible.
983  */
984 void
985 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
986 {
987         gchar *acc_name = NULL;
988
989         /* If no account name was provided get the current account, if
990            there is none either then pick the default one */
991         if (!account_name) {
992                 acc_name = g_strdup (modest_window_get_active_account(win));
993                 if (!acc_name)
994                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
995                 if (!acc_name) {
996                         g_printerr ("modest: cannot get default account\n");
997                         return;
998                 }
999         } else {
1000                 acc_name = g_strdup (account_name);
1001         }
1002
1003         /* Send & receive. */
1004         
1005         /* Do not continue if no suitable connection
1006            is open */
1007         if (!check_for_connection (acc_name)) {
1008                 g_free (acc_name);
1009                 return;
1010         }
1011         
1012         /* TODO: Do not continue if an operation is already in progress:
1013          * Maybe there are some operations that tinymail allows to 
1014          * happen simulatenously.
1015          * TODO: Maybe a simple global gboolean is_updating is enough?
1016          * murrayc.
1017          */
1018         
1019         /* As per the UI spec,
1020          * for POP accounts, we should receive,
1021          * for IMAP we should synchronize everything, including receiving,
1022          * for SMTP we should send,
1023          * first receiving, then sending:
1024          */
1025         /* Create the mail operation */
1026         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1027         ModestMailOperation *mail_op;
1028         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
1029         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1030         modest_mail_operation_update_account (mail_op, acc_name);
1031         g_object_unref (G_OBJECT (mail_op));
1032         
1033         /* Free */
1034         g_free (acc_name);
1035 }
1036
1037 /*
1038  * Refreshes all accounts. This function will be used by automatic
1039  * updates
1040  */
1041 void
1042 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1043 {
1044         GSList *account_names, *iter;
1045
1046         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1047                                                           TRUE);
1048
1049         iter = account_names;
1050         while (iter) {                  
1051                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1052                 iter = g_slist_next (iter);
1053         }
1054         
1055         g_slist_foreach (account_names, (GFunc) g_free, NULL);
1056         g_slist_free (account_names);
1057 }
1058
1059 /*
1060  * Handler of the click on Send&Receive button in the main toolbar
1061  */
1062 void
1063 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
1064 {
1065         /* Check that at least one account exists: */
1066         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
1067                                 TRUE /* enabled accounts only */);
1068         gboolean accounts_exist = account_names != NULL;
1069         g_slist_free (account_names);
1070         
1071         /* If not, allow the user to create an account before trying to send/receive. */
1072         if (!accounts_exist)
1073                 modest_ui_actions_on_accounts (NULL, win);
1074         
1075         /* Refresh the active account */
1076         modest_ui_actions_do_send_receive (NULL, win);
1077 }
1078
1079
1080 void
1081 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1082 {
1083         ModestConf *conf;
1084         GtkWidget *header_view;
1085         
1086         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1087
1088         header_view = modest_main_window_get_child_widget (main_window,
1089                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1090         if (!header_view)
1091                 return;
1092
1093         conf = modest_runtime_get_conf ();
1094         
1095         /* what is saved/restored is depending on the style; thus; we save with
1096          * old style, then update the style, and restore for this new style
1097          */
1098         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1099         
1100         if (modest_header_view_get_style
1101             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1102                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1103                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1104         else
1105                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1106                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1107
1108         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1109                                       MODEST_CONF_HEADER_VIEW_KEY);
1110 }
1111
1112
1113 void 
1114 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1115                                       TnyHeader *header,
1116                                       ModestMainWindow *main_window)
1117 {
1118         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1119
1120         /* If no header has been selected then exit */
1121         if (!header)
1122                 return;
1123
1124         /* Update Main window title */
1125         if (GTK_WIDGET_HAS_FOCUS (header_view)) {
1126                 const gchar *subject = tny_header_get_subject (header);
1127                 if (subject && strcmp (subject, ""))
1128                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
1129                 else
1130                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
1131         }
1132 }
1133
1134 void
1135 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1136                                        TnyHeader *header,
1137                                        ModestMainWindow *main_window)
1138 {
1139         TnyList *headers;
1140
1141         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1142         
1143         if (!header)
1144                 return;
1145
1146         headers = tny_simple_list_new ();
1147         tny_list_prepend (headers, G_OBJECT (header));
1148
1149         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1150
1151         g_object_unref (headers);
1152 }
1153
1154 static void
1155 set_active_account_from_tny_account (TnyAccount *account,
1156                                      ModestWindow *window)
1157 {
1158         const gchar *server_acc_name = tny_account_get_id (account);
1159         
1160         /* We need the TnyAccount provided by the
1161            account store because that is the one that
1162            knows the name of the Modest account */
1163         TnyAccount *modest_server_account = modest_server_account = 
1164                 modest_tny_account_store_get_tny_account_by_id  (modest_runtime_get_account_store (), 
1165                                                                  server_acc_name);
1166         
1167         const gchar *modest_acc_name = 
1168                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1169         modest_window_set_active_account (window, modest_acc_name);
1170         g_object_unref (modest_server_account);
1171 }
1172
1173 void 
1174 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1175                                                TnyFolderStore *folder_store, 
1176                                                gboolean selected,
1177                                                ModestMainWindow *main_window)
1178 {
1179         ModestConf *conf;
1180         GtkWidget *header_view;
1181         
1182         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1183
1184         header_view = modest_main_window_get_child_widget(main_window,
1185                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1186         if (!header_view)
1187                 return;
1188         
1189         conf = modest_runtime_get_conf ();
1190
1191         if (TNY_IS_ACCOUNT (folder_store)) {
1192                 /* Update active account */
1193                 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1194                 /* Show account details */
1195                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1196         } else if (modest_tny_folder_store_is_virtual_local_folders  (folder_store )) {
1197                 printf ("DEBUG: %s: folder store.\n", __FUNCTION__);
1198                 //TODO: Set the virtual folder store as the "active account" somehow:
1199                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1200         } else {
1201                 if (TNY_IS_FOLDER (folder_store) && selected) {
1202                         
1203                         if (!TNY_IS_MERGE_FOLDER (folder_store)) { /* TnyMergeFolder can have no get_account() implementation. */
1204                                 /* Update the active account */
1205                                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder_store));
1206                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1207                                 g_object_unref (account);
1208                         }
1209                         
1210                         /* Set folder on header view */
1211                         modest_main_window_set_contents_style (main_window, 
1212                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1213                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1214                                                        TNY_FOLDER (folder_store));
1215                         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1216                                                       MODEST_CONF_HEADER_VIEW_KEY);
1217                 } else {
1218                         /* Update the active account */
1219                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1220                         /* Do not show folder */
1221                         modest_widget_memory_save (conf, G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
1222                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
1223                 }
1224         }
1225 }
1226
1227 void 
1228 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1229                                      ModestWindow *win)
1230 {
1231         GtkWidget *dialog;
1232         gchar *txt, *item;
1233         gboolean online;
1234
1235         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1236         
1237         if (g_main_depth > 0)   
1238                 gdk_threads_enter ();
1239         online = tny_device_is_online (modest_runtime_get_device());
1240
1241         if (online) {
1242                 /* already online -- the item is simply not there... */
1243                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1244                                                  GTK_DIALOG_MODAL,
1245                                                  GTK_MESSAGE_WARNING,
1246                                                  GTK_BUTTONS_OK,
1247                                                  _("The %s you selected cannot be found"),
1248                                                  item);
1249                 gtk_dialog_run (GTK_DIALOG(dialog));
1250         } else {
1251                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1252                                                       GTK_WINDOW (win),
1253                                                       GTK_DIALOG_MODAL,
1254                                                       GTK_STOCK_CANCEL,
1255                                                       GTK_RESPONSE_REJECT,
1256                                                       GTK_STOCK_OK,
1257                                                       GTK_RESPONSE_ACCEPT,
1258                                                       NULL);
1259                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1260                                          "Do you want to get online?"), item);
1261                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1262                                     gtk_label_new (txt), FALSE, FALSE, 0);
1263                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1264                 g_free (txt);
1265
1266                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1267                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1268 //                      modest_platform_connect_and_wait ();;
1269                 }
1270         }
1271         gtk_widget_destroy (dialog);
1272         if (g_main_depth > 0)   
1273                 gdk_threads_leave ();
1274 }
1275
1276 void
1277 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1278                                      ModestWindow *win)
1279 {
1280         /* g_message ("%s %s", __FUNCTION__, link); */
1281 }       
1282
1283
1284 void
1285 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1286                                         ModestWindow *win)
1287 {
1288         modest_platform_activate_uri (link);
1289 }
1290
1291 void
1292 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1293                                           ModestWindow *win)
1294 {
1295         modest_platform_show_uri_popup (link);
1296 }
1297
1298 void
1299 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1300                                              ModestWindow *win)
1301 {
1302         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1303 }
1304
1305 void
1306 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1307                                           const gchar *address,
1308                                           ModestWindow *win)
1309 {
1310         /* g_message ("%s %s", __FUNCTION__, address); */
1311 }
1312
1313 void
1314 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1315 {
1316         TnyTransportAccount *transport_account;
1317         ModestMailOperation *mail_operation;
1318         MsgData *data;
1319         gchar *account_name, *from;
1320         ModestAccountMgr *account_mgr;
1321
1322         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1323         
1324         data = modest_msg_edit_window_get_msg_data (edit_window);
1325
1326         account_mgr = modest_runtime_get_account_mgr();
1327         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1328         if (!account_name) 
1329                 account_name = modest_account_mgr_get_default_account (account_mgr);
1330         if (!account_name) {
1331                 g_printerr ("modest: no account found\n");
1332                 modest_msg_edit_window_free_msg_data (edit_window, data);
1333                 return;
1334         }
1335         transport_account =
1336                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1337                                       (modest_runtime_get_account_store(),
1338                                        account_name,
1339                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1340         if (!transport_account) {
1341                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1342                 g_free (account_name);
1343                 modest_msg_edit_window_free_msg_data (edit_window, data);
1344                 return;
1345         }
1346         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1347
1348         /* Create the mail operation */         
1349         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1350         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1351
1352         modest_mail_operation_save_to_drafts (mail_operation,
1353                                               transport_account,
1354                                               from,
1355                                               data->to, 
1356                                               data->cc, 
1357                                               data->bcc,
1358                                               data->subject, 
1359                                               data->plain_body, 
1360                                               data->html_body,
1361                                               data->attachments,
1362                                               data->priority_flags);
1363         /* Frees */
1364         g_free (from);
1365         g_free (account_name);
1366         g_object_unref (G_OBJECT (transport_account));
1367         g_object_unref (G_OBJECT (mail_operation));
1368
1369         modest_msg_edit_window_free_msg_data (edit_window, data);
1370
1371         /* Save settings and close the window */
1372         gtk_widget_destroy (GTK_WIDGET (edit_window));
1373 }
1374
1375 /* For instance, when clicking the Send toolbar button when editing a message: */
1376 void
1377 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1378 {
1379         TnyTransportAccount *transport_account;
1380         ModestMailOperation *mail_operation;
1381         MsgData *data;
1382         gchar *account_name, *from;
1383         ModestAccountMgr *account_mgr;
1384
1385         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1386
1387         if (!modest_msg_edit_window_check_names (edit_window))
1388                 return;
1389         
1390         data = modest_msg_edit_window_get_msg_data (edit_window);
1391
1392         /* FIXME: Code added just for testing. The final version will
1393            use the send queue provided by tinymail and some
1394            classifier */
1395         account_mgr = modest_runtime_get_account_mgr();
1396         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1397         if (!account_name) 
1398                 account_name = modest_account_mgr_get_default_account (account_mgr);
1399         if (!account_name) {
1400                 g_printerr ("modest: no account found\n");
1401                 modest_msg_edit_window_free_msg_data (edit_window, data);
1402                 return;
1403         }
1404         transport_account =
1405                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1406                                       (modest_runtime_get_account_store(),
1407                                        account_name));
1408         if (!transport_account) {
1409                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1410                 g_free (account_name);
1411                 modest_msg_edit_window_free_msg_data (edit_window, data);
1412                 return;
1413         }
1414         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1415
1416         /* Create the mail operation */         
1417         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
1418         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1419
1420         modest_mail_operation_send_new_mail (mail_operation,
1421                                              transport_account,
1422                                              from,
1423                                              data->to, 
1424                                              data->cc, 
1425                                              data->bcc,
1426                                              data->subject, 
1427                                              data->plain_body, 
1428                                              data->html_body,
1429                                              data->attachments,
1430                                              data->priority_flags);
1431         /* Frees */
1432         g_free (from);
1433         g_free (account_name);
1434         g_object_unref (G_OBJECT (transport_account));
1435         g_object_unref (G_OBJECT (mail_operation));
1436
1437         modest_msg_edit_window_free_msg_data (edit_window, data);
1438
1439         /* Save settings and close the window */
1440         gtk_widget_destroy (GTK_WIDGET (edit_window));
1441 }
1442
1443 void 
1444 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1445                                   ModestMsgEditWindow *window)
1446 {
1447         ModestMsgEditFormatState *format_state = NULL;
1448
1449         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1450         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1451
1452         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1453                 return;
1454
1455         format_state = modest_msg_edit_window_get_format_state (window);
1456         g_return_if_fail (format_state != NULL);
1457
1458         format_state->bold = gtk_toggle_action_get_active (action);
1459         modest_msg_edit_window_set_format_state (window, format_state);
1460         g_free (format_state);
1461         
1462 }
1463
1464 void 
1465 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1466                                      ModestMsgEditWindow *window)
1467 {
1468         ModestMsgEditFormatState *format_state = NULL;
1469
1470         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1471         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1472
1473         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1474                 return;
1475
1476         format_state = modest_msg_edit_window_get_format_state (window);
1477         g_return_if_fail (format_state != NULL);
1478
1479         format_state->italics = gtk_toggle_action_get_active (action);
1480         modest_msg_edit_window_set_format_state (window, format_state);
1481         g_free (format_state);
1482         
1483 }
1484
1485 void 
1486 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1487                                      ModestMsgEditWindow *window)
1488 {
1489         ModestMsgEditFormatState *format_state = NULL;
1490
1491         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1492         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1493
1494         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1495                 return;
1496
1497         format_state = modest_msg_edit_window_get_format_state (window);
1498         g_return_if_fail (format_state != NULL);
1499
1500         format_state->bullet = gtk_toggle_action_get_active (action);
1501         modest_msg_edit_window_set_format_state (window, format_state);
1502         g_free (format_state);
1503         
1504 }
1505
1506 void 
1507 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1508                                      GtkRadioAction *selected,
1509                                      ModestMsgEditWindow *window)
1510 {
1511         ModestMsgEditFormatState *format_state = NULL;
1512         GtkJustification value;
1513
1514         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1515
1516         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1517                 return;
1518
1519         value = gtk_radio_action_get_current_value (selected);
1520
1521         format_state = modest_msg_edit_window_get_format_state (window);
1522         g_return_if_fail (format_state != NULL);
1523
1524         format_state->justification = value;
1525         modest_msg_edit_window_set_format_state (window, format_state);
1526         g_free (format_state);
1527 }
1528
1529 void 
1530 modest_ui_actions_on_select_editor_color (GtkAction *action,
1531                                           ModestMsgEditWindow *window)
1532 {
1533         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1534         g_return_if_fail (GTK_IS_ACTION (action));
1535
1536         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1537                 return;
1538
1539         modest_msg_edit_window_select_color (window);
1540 }
1541
1542 void 
1543 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1544                                                      ModestMsgEditWindow *window)
1545 {
1546         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1547         g_return_if_fail (GTK_IS_ACTION (action));
1548
1549         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1550                 return;
1551
1552         modest_msg_edit_window_select_background_color (window);
1553 }
1554
1555 void 
1556 modest_ui_actions_on_insert_image (GtkAction *action,
1557                                    ModestMsgEditWindow *window)
1558 {
1559         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1560         g_return_if_fail (GTK_IS_ACTION (action));
1561
1562         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1563                 return;
1564
1565         modest_msg_edit_window_insert_image (window);
1566 }
1567
1568 void 
1569 modest_ui_actions_on_attach_file (GtkAction *action,
1570                                   ModestMsgEditWindow *window)
1571 {
1572         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1573         g_return_if_fail (GTK_IS_ACTION (action));
1574
1575         modest_msg_edit_window_attach_file (window);
1576 }
1577
1578 void 
1579 modest_ui_actions_on_remove_attachments (GtkAction *action,
1580                                          ModestMsgEditWindow *window)
1581 {
1582         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1583         g_return_if_fail (GTK_IS_ACTION (action));
1584
1585         modest_msg_edit_window_remove_attachments (window, NULL);
1586 }
1587
1588 /*
1589  * Shows a dialog with an entry that asks for some text. The returned
1590  * value must be freed by the caller. The dialog window title will be
1591  * set to @title.
1592  */
1593 static gchar *
1594 ask_for_folder_name (GtkWindow *parent_window,
1595                      const gchar *title)
1596 {
1597         GtkWidget *dialog, *entry;
1598         gchar *folder_name = NULL;
1599
1600         /* Ask for folder name */
1601         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1602                                               parent_window,
1603                                               GTK_DIALOG_MODAL,
1604                                               GTK_STOCK_CANCEL,
1605                                               GTK_RESPONSE_REJECT,
1606                                               GTK_STOCK_OK,
1607                                               GTK_RESPONSE_ACCEPT,
1608                                               NULL);
1609         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1610                             gtk_label_new(title),
1611                             FALSE, FALSE, 0);
1612                 
1613         entry = gtk_entry_new_with_max_length (40);
1614         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1615                             entry,
1616                             TRUE, FALSE, 0);    
1617         
1618         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1619         
1620         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1621                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1622
1623         gtk_widget_destroy (dialog);
1624
1625         return folder_name;
1626 }
1627
1628 void 
1629 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1630 {
1631         TnyFolderStore *parent_folder;
1632         GtkWidget *folder_view;
1633         
1634         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1635
1636         folder_view = modest_main_window_get_child_widget (main_window,
1637                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1638         if (!folder_view)
1639                 return;
1640
1641         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1642         
1643         if (parent_folder) {
1644                 gboolean finished = FALSE;
1645                 gint result;
1646                 gchar *folder_name = NULL, *suggested_name = NULL;
1647
1648                 /* Run the new folder dialog */
1649                 while (!finished) {
1650                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
1651                                                                         parent_folder,
1652                                                                         suggested_name,
1653                                                                         &folder_name);
1654
1655                         if (result == GTK_RESPONSE_REJECT) {
1656                                 finished = TRUE;
1657                         } else {
1658                                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(main_window));
1659                                 TnyFolder *new_folder = NULL;
1660
1661                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1662                                                                  mail_op);
1663                 
1664                                 new_folder = modest_mail_operation_create_folder (mail_op,
1665                                                                                   parent_folder,
1666                                                                                   (const gchar *) folder_name);
1667                                 if (new_folder) {
1668                                         g_object_unref (new_folder);
1669                                         finished = TRUE;
1670                                 } 
1671 /*                              else { */
1672 /*                                      /\* TODO: check error and follow proper actions *\/ */
1673 /* /\*                                  suggested_name = X; *\/ */
1674 /*                                      /\* Show error to the user *\/ */
1675 /*                                      modest_platform_run_information_dialog (GTK_WINDOW (main_window), */
1676 /*                                                                              _("mail_in_ui_folder_create_error")); */
1677 /*                              } */
1678                                 g_object_unref (mail_op);
1679                         }
1680                         g_free (folder_name);
1681                         folder_name = NULL;
1682                 }
1683
1684                 g_object_unref (parent_folder);
1685         }
1686 }
1687
1688 void 
1689 modest_ui_actions_on_rename_folder (GtkAction *action,
1690                                      ModestMainWindow *main_window)
1691 {
1692         TnyFolderStore *folder;
1693         GtkWidget *folder_view;
1694         GtkWidget *header_view; 
1695
1696         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1697
1698         folder_view = modest_main_window_get_child_widget (main_window,
1699                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1700         if (!folder_view)
1701                 return;
1702
1703         header_view = modest_main_window_get_child_widget (main_window,
1704                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1705         
1706         if (!header_view)
1707                 return;
1708
1709         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1710         
1711         if (folder && TNY_IS_FOLDER (folder)) {
1712                 gchar *folder_name;
1713                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1714                                                    _("Please enter a new name for the folder"));
1715
1716                 if (folder_name != NULL && strlen (folder_name) > 0) {
1717                         ModestMailOperation *mail_op;
1718
1719                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(main_window));
1720                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1721                                                          mail_op);
1722
1723                         modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL);
1724
1725                         modest_mail_operation_rename_folder (mail_op,
1726                                                              TNY_FOLDER (folder),
1727                                                              (const gchar *) folder_name);
1728
1729                         g_object_unref (mail_op);
1730                         g_free (folder_name);
1731                 }
1732                 g_object_unref (folder);
1733         }
1734 }
1735
1736 static void
1737 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1738 {
1739         TnyFolderStore *folder;
1740         GtkWidget *folder_view;
1741         gint response;
1742         gchar *message;
1743         
1744         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1745
1746         folder_view = modest_main_window_get_child_widget (main_window,
1747                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1748         if (!folder_view)
1749                 return;
1750
1751         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1752
1753         /* Show an error if it's an account */
1754         if (!TNY_IS_FOLDER (folder)) {
1755                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1756                                                         _("mail_in_ui_folder_delete_error"));
1757                 return ;
1758         }
1759
1760         /* Ask the user */      
1761         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
1762                                     tny_folder_get_name (TNY_FOLDER (folder)));
1763         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window), 
1764                                                             (const gchar *) message);
1765         g_free (message);
1766
1767         if (response == GTK_RESPONSE_OK) {
1768                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, G_OBJECT(main_window));
1769
1770                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1771                                                  mail_op);
1772                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1773
1774                 /* Show error if happened */
1775                 if (modest_mail_operation_get_error (mail_op))
1776                         modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1777                                                                 _("mail_in_ui_folder_delete_error"));
1778
1779                 g_object_unref (G_OBJECT (mail_op));
1780         }
1781
1782         g_object_unref (G_OBJECT (folder));
1783 }
1784
1785 void 
1786 modest_ui_actions_on_delete_folder (GtkAction *action,
1787                                      ModestMainWindow *main_window)
1788 {
1789         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1790
1791         delete_folder (main_window, FALSE);
1792 }
1793
1794 void 
1795 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1796 {
1797         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1798         
1799         delete_folder (main_window, TRUE);
1800 }
1801
1802 void
1803 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1804                                          const gchar* server_account_name,
1805                                          gchar **username,
1806                                          gchar **password, 
1807                                          gboolean *cancel, 
1808                                          gboolean *remember,
1809                                          ModestMainWindow *main_window)
1810 {
1811         g_return_if_fail(server_account_name);
1812         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
1813         
1814         /* Initalize output parameters: */
1815         if (cancel)
1816                 *cancel = FALSE;
1817                 
1818         if (remember)
1819                 *remember = TRUE;
1820                 
1821 #ifdef MODEST_PLATFORM_MAEMO
1822         /* Maemo uses a different (awkward) button order,
1823          * It should probably just use gtk_alternative_dialog_button_order ().
1824          */
1825         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1826                                               NULL,
1827                                               GTK_DIALOG_MODAL,
1828                                               GTK_STOCK_OK,
1829                                               GTK_RESPONSE_ACCEPT,
1830                                               GTK_STOCK_CANCEL,
1831                                               GTK_RESPONSE_REJECT,
1832                                               NULL);
1833 #else
1834         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1835                                               NULL,
1836                                               GTK_DIALOG_MODAL,
1837                                               GTK_STOCK_CANCEL,
1838                                               GTK_RESPONSE_REJECT,
1839                                               GTK_STOCK_OK,
1840                                               GTK_RESPONSE_ACCEPT,
1841                                               NULL);
1842 #endif /* MODEST_PLATFORM_MAEMO */
1843
1844         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1845         
1846         gchar *server_name = modest_server_account_get_hostname (
1847                 modest_runtime_get_account_mgr(), server_account_name);
1848         
1849         /* This causes a warning because the logical ID has no %s in it, 
1850          * though the translation does, but there is not much we can do about that: */
1851         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
1852         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1853                             FALSE, FALSE, 0);
1854         g_free (txt);
1855         g_free (server_name);
1856         server_name = NULL;
1857
1858         /* username: */
1859         gchar *initial_username = modest_server_account_get_username (
1860                 modest_runtime_get_account_mgr(), server_account_name);
1861         
1862         GtkWidget *entry_username = gtk_entry_new ();
1863         if (initial_username)
1864                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
1865         /* Dim this if a connection has ever succeeded with this username,
1866          * as per the UI spec: */
1867         const gboolean username_known = 
1868                 modest_server_account_get_username_has_succeeded(
1869                         modest_runtime_get_account_mgr(), server_account_name);
1870         gtk_widget_set_sensitive (entry_username, !username_known);
1871         
1872 #ifdef MODEST_PLATFORM_MAEMO
1873         /* Auto-capitalization is the default, so let's turn it off: */
1874         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
1875         
1876         /* Create a size group to be used by all captions.
1877          * Note that HildonCaption does not create a default size group if we do not specify one.
1878          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
1879         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1880         
1881         GtkWidget *caption = hildon_caption_new (sizegroup, 
1882                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
1883         gtk_widget_show (entry_username);
1884         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1885                 FALSE, FALSE, MODEST_MARGIN_HALF);
1886         gtk_widget_show (caption);
1887 #else 
1888         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
1889                             TRUE, FALSE, 0);
1890 #endif /* MODEST_PLATFORM_MAEMO */      
1891                             
1892         /* password: */
1893         GtkWidget *entry_password = gtk_entry_new ();
1894         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
1895         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
1896         
1897 #ifdef MODEST_PLATFORM_MAEMO
1898         /* Auto-capitalization is the default, so let's turn it off: */
1899         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
1900                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
1901         
1902         caption = hildon_caption_new (sizegroup, 
1903                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
1904         gtk_widget_show (entry_password);
1905         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1906                 FALSE, FALSE, MODEST_MARGIN_HALF);
1907         gtk_widget_show (caption);
1908         g_object_unref (sizegroup);
1909 #else 
1910         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
1911                             TRUE, FALSE, 0);
1912 #endif /* MODEST_PLATFORM_MAEMO */      
1913                                 
1914 /* This is not in the Maemo UI spec:
1915         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1916         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1917                             TRUE, FALSE, 0);
1918 */
1919
1920         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1921         
1922         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1923                 if (username) {
1924                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
1925                         
1926                         modest_server_account_set_username (
1927                                  modest_runtime_get_account_mgr(), server_account_name, 
1928                                  *username);
1929                                  
1930                         const gboolean username_was_changed = 
1931                                 (strcmp (*username, initial_username) != 0);
1932                         if (username_was_changed) {
1933                                 /* To actually use a changed username, 
1934                                  * we must reset the connection, according to pvanhoof.
1935                                  * This _might_ be a sensible way to do that: */
1936                                  TnyDevice *device = modest_runtime_get_device();
1937                                  tny_device_force_offline (device);
1938                                  tny_device_force_online (device);
1939                         }
1940                 }
1941                         
1942                 if (password) {
1943                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
1944                         
1945                         /* We do not save the password in the configuration, 
1946                          * because this function is only called for passwords that should 
1947                          * not be remembered:
1948                         modest_server_account_set_password (
1949                                  modest_runtime_get_account_mgr(), server_account_name, 
1950                                  *password);
1951                         */
1952                 }
1953                 
1954                 if (cancel)
1955                         *cancel   = FALSE;
1956                         
1957         } else {
1958                 if (username)
1959                         *username = NULL;
1960                         
1961                 if (password)
1962                         *password = NULL;
1963                         
1964                 if (cancel)
1965                         *cancel   = TRUE;
1966         }
1967
1968 /* This is not in the Maemo UI spec:
1969         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1970                 *remember = TRUE;
1971         else
1972                 *remember = FALSE;
1973 */
1974
1975         gtk_widget_destroy (dialog);
1976         
1977         printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel);
1978 }
1979
1980 void
1981 modest_ui_actions_on_cut (GtkAction *action,
1982                           ModestWindow *window)
1983 {
1984         GtkWidget *focused_widget;
1985
1986         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1987         if (GTK_IS_EDITABLE (focused_widget)) {
1988                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1989         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1990                 GtkTextBuffer *buffer;
1991                 GtkClipboard *clipboard;
1992
1993                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1994                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1995                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1996         }
1997 }
1998
1999 void
2000 modest_ui_actions_on_copy (GtkAction *action,
2001                            ModestWindow *window)
2002 {
2003         GtkClipboard *clipboard;
2004         GtkWidget *focused_widget;
2005
2006         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
2007         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2008         if (GTK_IS_LABEL (focused_widget)) {
2009                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2010         } else if (GTK_IS_EDITABLE (focused_widget)) {
2011                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2012         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2013                 GtkTextBuffer *buffer;
2014
2015                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2016                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2017         }
2018 }
2019
2020 void
2021 modest_ui_actions_on_undo (GtkAction *action,
2022                            ModestWindow *window)
2023 {
2024         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2025                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2026         } else {
2027                 g_return_if_reached ();
2028         }
2029 }
2030
2031 void
2032 modest_ui_actions_on_paste (GtkAction *action,
2033                             ModestWindow *window)
2034 {
2035         GtkWidget *focused_widget;
2036
2037         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2038         if (GTK_IS_EDITABLE (focused_widget)) {
2039                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2040         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2041                 GtkTextBuffer *buffer;
2042                 GtkClipboard *clipboard;
2043
2044                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
2045                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2046                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2047         }
2048 }
2049
2050 void
2051 modest_ui_actions_on_select_all (GtkAction *action,
2052                                  ModestWindow *window)
2053 {
2054         GtkWidget *focused_widget;
2055
2056         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2057         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2058                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2059         } else if (GTK_IS_LABEL (focused_widget)) {
2060                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2061         } else if (GTK_IS_EDITABLE (focused_widget)) {
2062                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2063         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2064                 GtkTextBuffer *buffer;
2065                 GtkTextIter start, end;
2066
2067                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2068                 gtk_text_buffer_get_start_iter (buffer, &start);
2069                 gtk_text_buffer_get_end_iter (buffer, &end);
2070                 gtk_text_buffer_select_range (buffer, &start, &end);
2071         }
2072 }
2073
2074 void
2075 modest_ui_actions_on_mark_as_read (GtkAction *action,
2076                                    ModestWindow *window)
2077 {       
2078         g_return_if_fail (MODEST_IS_WINDOW(window));
2079                 
2080         /* Mark each header as read */
2081         do_headers_action (window, headers_action_mark_as_read, NULL);
2082 }
2083
2084 void
2085 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2086                                      ModestWindow *window)
2087 {       
2088         g_return_if_fail (MODEST_IS_WINDOW(window));
2089                 
2090         /* Mark each header as read */
2091         do_headers_action (window, headers_action_mark_as_unread, NULL);
2092 }
2093
2094 void
2095 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2096                                   GtkRadioAction *selected,
2097                                   ModestWindow *window)
2098 {
2099         gint value;
2100
2101         value = gtk_radio_action_get_current_value (selected);
2102         if (MODEST_IS_WINDOW (window)) {
2103                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2104         }
2105 }
2106
2107 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2108                                                         GtkRadioAction *selected,
2109                                                         ModestWindow *window)
2110 {
2111         TnyHeaderFlags flags;
2112         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2113
2114         flags = gtk_radio_action_get_current_value (selected);
2115         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2116 }
2117
2118 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2119                                                            GtkRadioAction *selected,
2120                                                            ModestWindow *window)
2121 {
2122         gint file_format;
2123
2124         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2125
2126         file_format = gtk_radio_action_get_current_value (selected);
2127         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2128 }
2129
2130
2131 void     
2132 modest_ui_actions_on_zoom_plus (GtkAction *action,
2133                                 ModestWindow *window)
2134 {
2135         g_return_if_fail (MODEST_IS_WINDOW (window));
2136
2137         modest_window_zoom_plus (MODEST_WINDOW (window));
2138 }
2139
2140 void     
2141 modest_ui_actions_on_zoom_minus (GtkAction *action,
2142                                  ModestWindow *window)
2143 {
2144         g_return_if_fail (MODEST_IS_WINDOW (window));
2145
2146         modest_window_zoom_minus (MODEST_WINDOW (window));
2147 }
2148
2149 void     
2150 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2151                                            ModestWindow *window)
2152 {
2153         ModestWindowMgr *mgr;
2154         gboolean fullscreen, active;
2155         g_return_if_fail (MODEST_IS_WINDOW (window));
2156
2157         mgr = modest_runtime_get_window_mgr ();
2158
2159         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2160         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2161
2162         if (active != fullscreen) {
2163                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2164                 gtk_window_present (GTK_WINDOW (window));
2165         }
2166 }
2167
2168 void
2169 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2170                                         ModestWindow *window)
2171 {
2172         ModestWindowMgr *mgr;
2173         gboolean fullscreen;
2174
2175         g_return_if_fail (MODEST_IS_WINDOW (window));
2176
2177         mgr = modest_runtime_get_window_mgr ();
2178         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2179         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2180
2181         gtk_window_present (GTK_WINDOW (window));
2182 }
2183
2184 /* 
2185  * Used by modest_ui_actions_on_details to call do_headers_action 
2186  */
2187 static void
2188 headers_action_show_details (TnyHeader *header, 
2189                              ModestWindow *window,
2190                              gpointer user_data)
2191
2192 {
2193         GtkWidget *dialog;
2194         
2195         /* Create dialog */
2196         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2197
2198         /* Run dialog */
2199         gtk_widget_show_all (dialog);
2200         gtk_dialog_run (GTK_DIALOG (dialog));
2201
2202         gtk_widget_destroy (dialog);
2203 }
2204
2205 /*
2206  * Show the folder details in a ModestDetailsDialog widget
2207  */
2208 static void
2209 show_folder_details (TnyFolder *folder, 
2210                      GtkWindow *window)
2211 {
2212         GtkWidget *dialog;
2213         
2214         /* Create dialog */
2215         dialog = modest_details_dialog_new_with_folder (window, folder);
2216
2217         /* Run dialog */
2218         gtk_widget_show_all (dialog);
2219         gtk_dialog_run (GTK_DIALOG (dialog));
2220
2221         gtk_widget_destroy (dialog);
2222 }
2223
2224 /*
2225  * Show the header details in a ModestDetailsDialog widget
2226  */
2227 void     
2228 modest_ui_actions_on_details (GtkAction *action, 
2229                               ModestWindow *win)
2230 {
2231         TnyList * headers_list;
2232         TnyIterator *iter;
2233         TnyHeader *header;              
2234
2235         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2236                 TnyMsg *msg;
2237
2238                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2239                 if (!msg)
2240                         return;
2241                 g_object_unref (msg);           
2242
2243                 headers_list = get_selected_headers (win);
2244                 if (!headers_list)
2245                         return;
2246
2247                 iter = tny_list_create_iterator (headers_list);
2248
2249                 header = TNY_HEADER (tny_iterator_get_current (iter));
2250                 headers_action_show_details (header, win, NULL);
2251                 g_object_unref (header);
2252
2253                 g_object_unref (iter);
2254                 g_object_unref (headers_list);
2255
2256         } else if (MODEST_IS_MAIN_WINDOW (win)) {
2257                 GtkWidget *folder_view, *header_view;
2258
2259                 /* Check which widget has the focus */
2260                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2261                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
2262                 if (gtk_widget_is_focus (folder_view)) {
2263                         TnyFolder *folder;
2264
2265                         folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2266
2267                         /* Show only when it's a folder */
2268                         if (!folder || !TNY_IS_FOLDER (folder))
2269                                 return;
2270
2271                         show_folder_details (folder, GTK_WINDOW (win));
2272
2273                 } else {
2274                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2275                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2276                         /* Show details of each header */
2277                         do_headers_action (win, headers_action_show_details, header_view);
2278                 }
2279         }
2280 }
2281
2282 void     
2283 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
2284                                      ModestMsgEditWindow *window)
2285 {
2286         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2287
2288         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
2289 }
2290
2291 void     
2292 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
2293                                       ModestMsgEditWindow *window)
2294 {
2295         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2296
2297         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
2298 }
2299
2300 void
2301 modest_ui_actions_toggle_folders_view (GtkAction *action, 
2302                                        ModestMainWindow *main_window)
2303 {
2304         ModestConf *conf;
2305         
2306         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2307
2308         conf = modest_runtime_get_conf ();
2309         
2310         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
2311                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
2312         else
2313                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
2314 }
2315
2316 void 
2317 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
2318                                      ModestWindow *window)
2319 {
2320         gboolean active, fullscreen = FALSE;
2321         ModestWindowMgr *mgr;
2322
2323         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
2324
2325         /* Check if we want to toggle the toolbar vuew in fullscreen
2326            or normal mode */
2327         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
2328                      "ViewShowToolbarFullScreen")) {
2329                 fullscreen = TRUE;
2330         }
2331
2332         /* Toggle toolbar */
2333         mgr = modest_runtime_get_window_mgr ();
2334         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
2335 }
2336
2337 void     
2338 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
2339                                            ModestMsgEditWindow *window)
2340 {
2341         modest_msg_edit_window_select_font (window);
2342 }
2343
2344 void
2345 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
2346                                                   const gchar *display_name,
2347                                                   GtkWindow *window)
2348 {
2349         /* Do not change the application name if the widget has not
2350            the focus. This callback could be called even if the folder
2351            view has not the focus, because the handled signal could be
2352            emitted when the folder view is redrawn */
2353         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
2354                 if (display_name)
2355                         gtk_window_set_title (window, display_name);
2356                 else
2357                         gtk_window_set_title (window, " ");
2358         }
2359 }
2360
2361 void
2362 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2363 {
2364         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2365         modest_msg_edit_window_select_contacts (window);
2366 }
2367
2368 void
2369 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2370 {
2371         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2372         modest_msg_edit_window_check_names (window);
2373 }
2374
2375
2376 static GtkWidget*
2377 create_move_to_dialog (ModestWindow *win,
2378                        GtkWidget *folder_view,
2379                        GtkWidget **tree_view)
2380 {
2381         GtkWidget *dialog, *scroll;
2382
2383         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2384                                               GTK_WINDOW (win),
2385                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2386                                               GTK_STOCK_OK,
2387                                               GTK_RESPONSE_ACCEPT,
2388                                               GTK_STOCK_CANCEL,
2389                                               GTK_RESPONSE_REJECT,
2390                                               NULL);
2391
2392         /* Create scrolled window */
2393         scroll = gtk_scrolled_window_new (NULL, NULL);
2394         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
2395                                          GTK_POLICY_AUTOMATIC,
2396                                          GTK_POLICY_AUTOMATIC);
2397
2398         /* Create folder view */
2399         *tree_view = modest_folder_view_new (NULL);
2400         gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2401                                  gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2402         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2403
2404         /* Add scroll to dialog */
2405         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
2406                             scroll, FALSE, FALSE, 0);
2407
2408         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2409
2410         return dialog;
2411 }
2412
2413 /*
2414  * Returns TRUE if at least one of the headers of the list belongs to
2415  * a message that has been fully retrieved.
2416  */
2417 static gboolean
2418 has_retrieved_msgs (TnyList *list)
2419 {
2420         TnyIterator *iter;
2421         gboolean found = FALSE;
2422
2423         iter = tny_list_create_iterator (list);
2424         while (tny_iterator_is_done (iter) && !found) {
2425                 TnyHeader *header;
2426                 TnyHeaderFlags flags;
2427
2428                 header = TNY_HEADER (tny_iterator_get_current (iter));
2429                 flags = tny_header_get_flags (header);
2430                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2431                         found = TRUE;
2432
2433                 if (!found)
2434                         tny_iterator_next (iter);
2435         }
2436         g_object_unref (iter);
2437
2438         return found;
2439 }
2440
2441 /*
2442  * Shows a confirmation dialog to the user when we're moving messages
2443  * from a remote server to the local storage. Returns the dialog
2444  * response. If it's other kind of movement the it always returns
2445  * GTK_RESPONSE_OK
2446  */
2447 static gint
2448 msgs_move_to_confirmation (GtkWindow *win,
2449                            TnyFolder *dest_folder,
2450                            TnyList *headers)
2451 {
2452         gint response = GTK_RESPONSE_OK;
2453
2454         /* If the destination is a local folder */
2455         if (modest_tny_folder_is_local_folder (dest_folder)) {
2456                 TnyFolder *src_folder;
2457                 TnyIterator *iter;
2458                 TnyHeader *header;
2459
2460                 /* Get source folder */
2461                 iter = tny_list_create_iterator (headers);
2462                 header = TNY_HEADER (tny_iterator_get_current (iter));
2463                 src_folder = tny_header_get_folder (header);
2464                 g_object_unref (header);
2465                 g_object_unref (iter);
2466
2467                 /* If the source is a remote folder */
2468                 if (!modest_tny_folder_is_local_folder (src_folder)) {
2469                         const gchar *message;
2470                         
2471                         if (tny_list_get_length (headers) == 1)
2472                                 if (has_retrieved_msgs (headers))
2473                                         message = _("mcen_nc_move_retrieve");
2474                                 else
2475                                         message = _("mcen_nc_move_header");
2476                         else
2477                                 if (has_retrieved_msgs (headers))
2478                                         message = _("mcen_nc_move_retrieves");
2479                                 else
2480                                         message = _("mcen_nc_move_headers");
2481                         
2482                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2483                                                                             (const gchar *) message);
2484                 }
2485                 g_object_unref (src_folder);
2486         }
2487         return response;
2488 }
2489
2490
2491 static void
2492 tranasfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
2493 {
2494         ModestMsgViewWindow *self = NULL;
2495         gboolean found = FALSE;
2496
2497         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
2498         self = MODEST_MSG_VIEW_WINDOW (object);
2499
2500         found = modest_msg_view_window_select_first_message (self);
2501         g_return_if_fail (found);
2502 }
2503
2504 static void
2505 move_to_error_checking (const GObject *obj, gpointer user_data)
2506 {
2507         ModestWindow *win = NULL;
2508         
2509         g_return_if_fail (MODEST_IS_WINDOW (obj));
2510         win = MODEST_WINDOW (obj);
2511
2512         /* TODO: show error message */
2513 /*      modest_platform_run_information_dialog (GTK_WINDOW (win), */
2514 /*                                              _("mail_in_ui_folder_move_target_error")); */
2515 }
2516
2517 /*
2518  * UI handler for the "Move to" action when invoked from the
2519  * ModestMainWindow
2520  */
2521 static void 
2522 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
2523                                           ModestMainWindow *win)
2524 {
2525         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
2526         GtkWidget *header_view = NULL;
2527         gint result;
2528         TnyFolderStore *folder_store = NULL;
2529         ModestMailOperation *mail_op = NULL;
2530
2531         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2532
2533         /* Get the folder view */
2534         folder_view = modest_main_window_get_child_widget (win,
2535                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2536
2537         /* Get header view */
2538         header_view = modest_main_window_get_child_widget (win,
2539                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2540
2541         /* Create and run the dialog */
2542         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2543         result = gtk_dialog_run (GTK_DIALOG(dialog));
2544         g_object_ref (tree_view);
2545
2546         /* We do this to save an indentation level ;-) */
2547         if (result != GTK_RESPONSE_ACCEPT)
2548                 goto end;
2549
2550         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2551
2552         if (TNY_IS_ACCOUNT (folder_store))
2553                 goto end;
2554
2555         /* Get folder or messages to transfer */
2556         if (gtk_widget_is_focus (folder_view)) {
2557                 TnyFolderStore *src_folder;
2558                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2559
2560                 /* Clean folder on header view before moving it */
2561                 modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL); 
2562
2563                 if (TNY_IS_FOLDER (src_folder)) {
2564                         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2565                                                                                  G_OBJECT(win),
2566                                                                                  move_to_error_checking);
2567                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2568                                                          mail_op);
2569
2570                         modest_mail_operation_xfer_folder (mail_op, 
2571                                                            TNY_FOLDER (src_folder),
2572                                                            folder_store,
2573                                                            TRUE);
2574                         g_object_unref (G_OBJECT (mail_op));
2575                         
2576                 }
2577
2578                 /* Frees */
2579                 g_object_unref (G_OBJECT (src_folder));
2580         } else {
2581                 if (gtk_widget_is_focus (header_view)) {
2582                         TnyList *headers;
2583                         gint response;
2584
2585                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2586
2587                         /* Ask for user confirmation */
2588                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2589                                                               TNY_FOLDER (folder_store), 
2590                                                               headers);
2591
2592                         /* Transfer messages */
2593                         if (response == GTK_RESPONSE_OK) {
2594                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
2595                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2596                                                                  mail_op);
2597
2598                                 modest_mail_operation_xfer_msgs (mail_op, 
2599                                                                  headers,
2600                                                                  TNY_FOLDER (folder_store),
2601                                                                  TRUE,
2602                                                                  NULL,
2603                                                                  NULL);
2604                                 g_object_unref (G_OBJECT (mail_op));
2605                         }
2606                         g_object_unref (headers);
2607                 }
2608         }
2609         g_object_unref (folder_store);
2610         
2611  end:
2612         gtk_widget_destroy (dialog);
2613 }
2614
2615
2616 /*
2617  * UI handler for the "Move to" action when invoked from the
2618  * ModestMsgViewWindow
2619  */
2620 static void 
2621 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
2622                                               ModestMsgViewWindow *win)
2623 {
2624         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2625         gint result;
2626         ModestMainWindow *main_window;
2627         TnyHeader *header;
2628         TnyList *headers;
2629
2630         /* Get the folder view */
2631         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2632         folder_view = modest_main_window_get_child_widget (main_window,
2633                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2634
2635         /* Create and run the dialog */
2636         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
2637         result = gtk_dialog_run (GTK_DIALOG(dialog));
2638         g_object_ref (tree_view);
2639
2640         if (result == GTK_RESPONSE_ACCEPT) {
2641                 TnyFolderStore *folder_store;
2642                 gint response;
2643
2644                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2645
2646                 /* Create header list */
2647                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
2648                 headers = tny_simple_list_new ();
2649                 tny_list_prepend (headers, G_OBJECT (header));
2650                 g_object_unref (header);
2651
2652                 /* Ask user for confirmation. MSG-NOT404 */
2653                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2654                                                       TNY_FOLDER (folder_store), 
2655                                                       headers);
2656
2657                 /* Transfer current msg */
2658                 if (response == GTK_RESPONSE_OK) {
2659                         ModestMailOperation *mail_op;
2660
2661                         /* Create mail op */
2662                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
2663                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2664                                                          mail_op);
2665                         
2666                         /* Transfer messages */
2667                         modest_mail_operation_xfer_msgs (mail_op, 
2668                                                          headers,
2669                                                          TNY_FOLDER (folder_store),
2670                                                          TRUE,
2671                                                          tranasfer_msgs_from_viewer_cb,
2672                                                          NULL);
2673                         g_object_unref (G_OBJECT (mail_op));
2674                 } 
2675                 g_object_unref (headers);
2676                 g_object_unref (folder_store);
2677         }
2678         gtk_widget_destroy (dialog);
2679 }
2680
2681 void 
2682 modest_ui_actions_on_move_to (GtkAction *action, 
2683                               ModestWindow *win)
2684 {
2685         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
2686                           MODEST_IS_MSG_VIEW_WINDOW (win));
2687
2688         if (MODEST_IS_MAIN_WINDOW (win)) 
2689                 modest_ui_actions_on_main_window_move_to (action, 
2690                                                           MODEST_MAIN_WINDOW (win));
2691         else
2692                 modest_ui_actions_on_msg_view_window_move_to (action, 
2693                                                               MODEST_MSG_VIEW_WINDOW (win));
2694 }
2695
2696 /*
2697  * Calls #HeadersFunc for each header already selected in the main
2698  * window or the message currently being shown in the msg view window
2699  */
2700 static void
2701 do_headers_action (ModestWindow *win, 
2702                    HeadersFunc func,
2703                    gpointer user_data)
2704 {
2705         TnyList *headers_list;
2706         TnyIterator *iter;
2707
2708         /* Get headers */
2709         headers_list = get_selected_headers (win);
2710         if (!headers_list)
2711                 return;
2712
2713         /* Call the function for each header */
2714         iter = tny_list_create_iterator (headers_list);
2715         while (!tny_iterator_is_done (iter)) {
2716                 TnyHeader *header;
2717
2718                 header = TNY_HEADER (tny_iterator_get_current (iter));
2719                 func (header, win, user_data);
2720                 g_object_unref (header);
2721                 tny_iterator_next (iter);
2722         }
2723         g_object_unref (iter);
2724         g_object_unref (headers_list);
2725 }
2726
2727 void 
2728 modest_ui_actions_view_attachment (GtkAction *action,
2729                                    ModestWindow *window)
2730 {
2731         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2732                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
2733         } else {
2734                 /* not supported window for this action */
2735                 g_return_if_reached ();
2736         }
2737 }
2738
2739 void
2740 modest_ui_actions_save_attachments (GtkAction *action,
2741                                     ModestWindow *window)
2742 {
2743         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2744                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2745         } else {
2746                 /* not supported window for this action */
2747                 g_return_if_reached ();
2748         }
2749 }
2750
2751 void
2752 modest_ui_actions_remove_attachments (GtkAction *action,
2753                                       ModestWindow *window)
2754 {
2755         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2756                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2757         } else {
2758                 /* not supported window for this action */
2759                 g_return_if_reached ();
2760         }
2761 }
2762
2763 void 
2764 modest_ui_actions_on_settings (GtkAction *action, 
2765                                ModestWindow *win)
2766 {
2767         GtkWidget *dialog;
2768
2769         dialog = modest_platform_get_global_settings_dialog ();
2770         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
2771         gtk_widget_show (dialog);
2772
2773         gtk_dialog_run (GTK_DIALOG (dialog));
2774
2775         gtk_widget_destroy (dialog);
2776 }
2777
2778 void 
2779 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
2780                                             ModestWindow *window)
2781 {
2782         ModestMailOperation *mail_op;
2783         TnyList *headers;
2784
2785         /* Get headers */
2786         headers = get_selected_headers (window);
2787         if (!headers)
2788                 return;
2789
2790         /* Create mail operation */
2791         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT (window));
2792         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2793         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
2794
2795         /* Frees */
2796         g_object_unref (headers);
2797         g_object_unref (mail_op);
2798 }