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