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