2007-05-23 Murray Cumming <murrayc@murrayc.com>
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29  
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <string.h>
36 #include <modest-runtime.h>
37 #include <modest-tny-folder.h>
38 #include <modest-tny-msg.h>
39 #include <modest-tny-account.h>
40 #include <modest-address-book.h>
41
42 #include "modest-ui-actions.h"
43
44 #include "modest-tny-platform-factory.h"
45 #include "modest-platform.h"
46
47 #ifdef MODEST_PLATFORM_MAEMO
48 #include "maemo/modest-osso-state-saving.h"
49 #endif /* MODEST_PLATFORM_MAEMO */
50
51 #include "widgets/modest-ui-constants.h"
52 #include <widgets/modest-main-window.h>
53 #include <widgets/modest-msg-view-window.h>
54 #include <widgets/modest-account-view-window.h>
55 #include <widgets/modest-details-dialog.h>
56 #include <widgets/modest-attachments-view.h>
57 #include "widgets/modest-global-settings-dialog.h"
58 #include "modest-connection-specific-smtp-window.h"
59 #include "modest-account-mgr-helpers.h"
60 #include "modest-mail-operation.h"
61 #include "modest-text-utils.h"
62
63 #ifdef MODEST_HAVE_EASYSETUP
64 #include "easysetup/modest-easysetup-wizard.h"
65 #endif /* MODEST_HAVE_EASYSETUP */
66
67 #include <modest-widget-memory.h>
68 #include <tny-error.h>
69 #include <tny-simple-list.h>
70 #include <tny-msg-view.h>
71 #include <tny-device.h>
72 #include <tny-merge-folder.h>
73
74 typedef struct _GetMsgAsyncHelper {     
75         ModestWindow *window;
76         ModestMailOperation *mail_op;
77         TnyIterator *iter;
78         guint num_ops;
79         GFunc func;     
80         gpointer user_data;
81 } GetMsgAsyncHelper;
82
83 typedef enum _ReplyForwardAction {
84         ACTION_REPLY,
85         ACTION_REPLY_TO_ALL,
86         ACTION_FORWARD
87 } ReplyForwardAction;
88
89 typedef struct _ReplyForwardHelper {
90         guint reply_forward_type;
91         ReplyForwardAction action;
92         gchar *account_name;
93 } ReplyForwardHelper;
94
95 /*
96  * The do_headers_action uses this kind of functions to perform some
97  * action to each member of a list of headers
98  */
99 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
100
101 static void
102 do_headers_action (ModestWindow *win, 
103                    HeadersFunc func,
104                    gpointer user_data);
105
106
107 static void     open_msg_cb            (ModestMailOperation *mail_op, 
108                                         TnyHeader *header, 
109                                         TnyMsg *msg,
110                                         gpointer user_data);
111
112 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
113                                         TnyHeader *header, 
114                                         TnyMsg *msg,
115                                         gpointer user_data);
116
117 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
118
119 static gchar*   ask_for_folder_name    (GtkWindow *parent_window, const gchar *title);
120
121 void   
122 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
123 {
124         GtkWidget *about;
125         const gchar *authors[] = {
126                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
127                 NULL
128         };
129         about = gtk_about_dialog_new ();
130         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
131         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
132         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
133                                         _("Copyright (c) 2006, Nokia Corporation\n"
134                                           "All rights reserved."));
135         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
136                                        _("a modest e-mail client\n\n"
137                                          "design and implementation: Dirk-Jan C. Binnema\n"
138                                          "contributions from the fine people at KC and Ig\n"
139                                          "uses the tinymail email framework written by Philip van Hoof"));
140         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
141         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
142         
143         gtk_dialog_run (GTK_DIALOG (about));
144         gtk_widget_destroy(about);
145 }
146
147 /*
148  * Gets the list of currently selected messages. If the win is the
149  * main window, then it returns a newly allocated list of the headers
150  * selected in the header view. If win is the msg view window, then
151  * the value returned is a list with just a single header.
152  *
153  * The caller of this funcion must free the list.
154  */
155 static TnyList *
156 get_selected_headers (ModestWindow *win)
157 {
158         if (MODEST_IS_MAIN_WINDOW(win)) {
159                 GtkWidget *header_view;         
160                 
161                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
162                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
163                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
164                 
165         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
166                 /* for MsgViewWindows, we simply return a list with one element */
167                 TnyHeader *header;
168                 TnyList *list = NULL;
169                 
170                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
171                 if (header != NULL) {
172                         list = tny_simple_list_new ();
173                         tny_list_prepend (list, G_OBJECT(header));
174                         g_object_unref (G_OBJECT(header));
175                 }
176
177                 return list;
178
179         } else
180                 return NULL;
181 }
182
183 static void
184 headers_action_mark_as_read (TnyHeader *header,
185                              ModestWindow *win,
186                              gpointer user_data)
187 {
188         TnyHeaderFlags flags;
189
190         g_return_if_fail (TNY_IS_HEADER(header));
191
192         flags = tny_header_get_flags (header);
193         if (flags & TNY_HEADER_FLAG_SEEN) return;
194         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
195 }
196
197 static void
198 headers_action_mark_as_unread (TnyHeader *header,
199                                ModestWindow *win,
200                                gpointer user_data)
201 {
202         TnyHeaderFlags flags;
203
204         g_return_if_fail (TNY_IS_HEADER(header));
205
206         flags = tny_header_get_flags (header);
207         if (flags & TNY_HEADER_FLAG_SEEN)  {
208                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
209         }
210 }
211
212
213 static void
214 headers_action_delete (TnyHeader *header,
215                        ModestWindow *win,
216                        gpointer user_data)
217 {
218         ModestMailOperation *mail_op = NULL;
219
220         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_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         /* We need the TnyAccount provided by the
1109            account store because that is the one that
1110            knows the name of the Modest account */
1111         TnyAccount *modest_server_account = modest_server_account = 
1112                 modest_tny_account_store_get_tny_account_by_id  (modest_runtime_get_account_store (), 
1113                                                                  server_acc_name);
1114         
1115         const gchar *modest_acc_name = 
1116                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1117         modest_window_set_active_account (window, modest_acc_name);
1118         g_object_unref (modest_server_account);
1119 }
1120
1121 void 
1122 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1123                                                TnyFolderStore *folder_store, 
1124                                                gboolean selected,
1125                                                ModestMainWindow *main_window)
1126 {
1127         ModestConf *conf;
1128         GtkWidget *header_view;
1129         
1130         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1131
1132         header_view = modest_main_window_get_child_widget(main_window,
1133                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1134         if (!header_view)
1135                 return;
1136         
1137         conf = modest_runtime_get_conf ();
1138
1139         if (TNY_IS_ACCOUNT (folder_store)) {
1140                 /* Update active account */
1141                 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1142                 /* Show account details */
1143                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1144         } else if (modest_tny_folder_store_is_virtual_local_folders  (folder_store )) {
1145                 printf ("DEBUG: %s: folder store.\n", __FUNCTION__);
1146                 //TODO: Set the virtual folder store as the "active account" somehow:
1147                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1148         } else {
1149                 if (TNY_IS_FOLDER (folder_store) && selected) {
1150                         
1151                         if (!TNY_IS_MERGE_FOLDER (folder_store)) { /* TnyMergeFolder can have no get_account() implementation. */
1152                                 /* Update the active account */
1153                                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder_store));
1154                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1155                                 g_object_unref (account);
1156                         }
1157                         
1158                         /* Set folder on header view */
1159                         modest_main_window_set_contents_style (main_window, 
1160                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1161                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1162                                                        TNY_FOLDER (folder_store));
1163                         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1164                                                       MODEST_CONF_HEADER_VIEW_KEY);
1165                 } else {
1166                         /* Update the active account */
1167                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1168                         /* Do not show folder */
1169                         modest_widget_memory_save (conf, G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
1170                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
1171                 }
1172         }
1173 }
1174
1175 void 
1176 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1177                                      ModestWindow *win)
1178 {
1179         GtkWidget *dialog;
1180         gchar *txt, *item;
1181         gboolean online;
1182
1183         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1184         
1185         if (g_main_depth > 0)   
1186                 gdk_threads_enter ();
1187         online = tny_device_is_online (modest_runtime_get_device());
1188
1189         if (online) {
1190                 /* already online -- the item is simply not there... */
1191                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1192                                                  GTK_DIALOG_MODAL,
1193                                                  GTK_MESSAGE_WARNING,
1194                                                  GTK_BUTTONS_OK,
1195                                                  _("The %s you selected cannot be found"),
1196                                                  item);
1197                 gtk_dialog_run (GTK_DIALOG(dialog));
1198         } else {
1199                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1200                                                       GTK_WINDOW (win),
1201                                                       GTK_DIALOG_MODAL,
1202                                                       GTK_STOCK_CANCEL,
1203                                                       GTK_RESPONSE_REJECT,
1204                                                       GTK_STOCK_OK,
1205                                                       GTK_RESPONSE_ACCEPT,
1206                                                       NULL);
1207                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1208                                          "Do you want to get online?"), item);
1209                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1210                                     gtk_label_new (txt), FALSE, FALSE, 0);
1211                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1212                 g_free (txt);
1213
1214                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1215                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1216 //                      modest_platform_connect_and_wait ();;
1217                 }
1218         }
1219         gtk_widget_destroy (dialog);
1220         if (g_main_depth > 0)   
1221                 gdk_threads_leave ();
1222 }
1223
1224 void
1225 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1226                                      ModestWindow *win)
1227 {
1228         /* g_message ("%s %s", __FUNCTION__, link); */
1229 }       
1230
1231
1232 void
1233 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1234                                         ModestWindow *win)
1235 {
1236         modest_platform_activate_uri (link);
1237 }
1238
1239 void
1240 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1241                                           ModestWindow *win)
1242 {
1243         modest_platform_show_uri_popup (link);
1244 }
1245
1246 void
1247 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1248                                              ModestWindow *win)
1249 {
1250         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1251 }
1252
1253 void
1254 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1255                                           const gchar *address,
1256                                           ModestWindow *win)
1257 {
1258         /* g_message ("%s %s", __FUNCTION__, address); */
1259 }
1260
1261 void
1262 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1263 {
1264         TnyTransportAccount *transport_account;
1265         ModestMailOperation *mail_operation;
1266         MsgData *data;
1267         gchar *account_name, *from;
1268         ModestAccountMgr *account_mgr;
1269
1270         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1271         
1272         data = modest_msg_edit_window_get_msg_data (edit_window);
1273
1274         account_mgr = modest_runtime_get_account_mgr();
1275         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1276         if (!account_name) 
1277                 account_name = modest_account_mgr_get_default_account (account_mgr);
1278         if (!account_name) {
1279                 g_printerr ("modest: no account found\n");
1280                 modest_msg_edit_window_free_msg_data (edit_window, data);
1281                 return;
1282         }
1283         transport_account =
1284                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1285                                       (modest_runtime_get_account_store(),
1286                                        account_name,
1287                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1288         if (!transport_account) {
1289                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1290                 g_free (account_name);
1291                 modest_msg_edit_window_free_msg_data (edit_window, data);
1292                 return;
1293         }
1294         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1295
1296         /* Create the mail operation */         
1297         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(edit_window));
1298         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1299
1300         modest_mail_operation_save_to_drafts (mail_operation,
1301                                               transport_account,
1302                                               from,
1303                                               data->to, 
1304                                               data->cc, 
1305                                               data->bcc,
1306                                               data->subject, 
1307                                               data->plain_body, 
1308                                               data->html_body,
1309                                               data->attachments,
1310                                               data->priority_flags);
1311         /* Frees */
1312         g_free (from);
1313         g_free (account_name);
1314         g_object_unref (G_OBJECT (transport_account));
1315         g_object_unref (G_OBJECT (mail_operation));
1316
1317         modest_msg_edit_window_free_msg_data (edit_window, data);
1318
1319         /* Save settings and close the window */
1320         gtk_widget_destroy (GTK_WIDGET (edit_window));
1321 }
1322
1323 /* For instance, when clicking the Send toolbar button when editing a message: */
1324 void
1325 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1326 {
1327         TnyTransportAccount *transport_account;
1328         ModestMailOperation *mail_operation;
1329         MsgData *data;
1330         gchar *account_name, *from;
1331         ModestAccountMgr *account_mgr;
1332
1333         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1334
1335         if (!modest_msg_edit_window_check_names (edit_window))
1336                 return;
1337         
1338         data = modest_msg_edit_window_get_msg_data (edit_window);
1339
1340         /* FIXME: Code added just for testing. The final version will
1341            use the send queue provided by tinymail and some
1342            classifier */
1343         account_mgr = modest_runtime_get_account_mgr();
1344         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1345         if (!account_name) 
1346                 account_name = modest_account_mgr_get_default_account (account_mgr);
1347         if (!account_name) {
1348                 g_printerr ("modest: no account found\n");
1349                 modest_msg_edit_window_free_msg_data (edit_window, data);
1350                 return;
1351         }
1352         transport_account =
1353                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1354                                       (modest_runtime_get_account_store(),
1355                                        account_name));
1356         if (!transport_account) {
1357                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1358                 g_free (account_name);
1359                 modest_msg_edit_window_free_msg_data (edit_window, data);
1360                 return;
1361         }
1362         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1363
1364         /* Create the mail operation */         
1365         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_SEND, G_OBJECT(edit_window));
1366         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1367
1368         modest_mail_operation_send_new_mail (mail_operation,
1369                                              transport_account,
1370                                              from,
1371                                              data->to, 
1372                                              data->cc, 
1373                                              data->bcc,
1374                                              data->subject, 
1375                                              data->plain_body, 
1376                                              data->html_body,
1377                                              data->attachments,
1378                                              data->priority_flags);
1379         /* Frees */
1380         g_free (from);
1381         g_free (account_name);
1382         g_object_unref (G_OBJECT (transport_account));
1383         g_object_unref (G_OBJECT (mail_operation));
1384
1385         modest_msg_edit_window_free_msg_data (edit_window, data);
1386
1387         /* Save settings and close the window */
1388         gtk_widget_destroy (GTK_WIDGET (edit_window));
1389 }
1390
1391 void 
1392 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1393                                   ModestMsgEditWindow *window)
1394 {
1395         ModestMsgEditFormatState *format_state = NULL;
1396
1397         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1398         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1399
1400         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1401                 return;
1402
1403         format_state = modest_msg_edit_window_get_format_state (window);
1404         g_return_if_fail (format_state != NULL);
1405
1406         format_state->bold = gtk_toggle_action_get_active (action);
1407         modest_msg_edit_window_set_format_state (window, format_state);
1408         g_free (format_state);
1409         
1410 }
1411
1412 void 
1413 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1414                                      ModestMsgEditWindow *window)
1415 {
1416         ModestMsgEditFormatState *format_state = NULL;
1417
1418         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1419         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1420
1421         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1422                 return;
1423
1424         format_state = modest_msg_edit_window_get_format_state (window);
1425         g_return_if_fail (format_state != NULL);
1426
1427         format_state->italics = gtk_toggle_action_get_active (action);
1428         modest_msg_edit_window_set_format_state (window, format_state);
1429         g_free (format_state);
1430         
1431 }
1432
1433 void 
1434 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1435                                      ModestMsgEditWindow *window)
1436 {
1437         ModestMsgEditFormatState *format_state = NULL;
1438
1439         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1440         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1441
1442         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1443                 return;
1444
1445         format_state = modest_msg_edit_window_get_format_state (window);
1446         g_return_if_fail (format_state != NULL);
1447
1448         format_state->bullet = gtk_toggle_action_get_active (action);
1449         modest_msg_edit_window_set_format_state (window, format_state);
1450         g_free (format_state);
1451         
1452 }
1453
1454 void 
1455 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1456                                      GtkRadioAction *selected,
1457                                      ModestMsgEditWindow *window)
1458 {
1459         ModestMsgEditFormatState *format_state = NULL;
1460         GtkJustification value;
1461
1462         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1463
1464         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1465                 return;
1466
1467         value = gtk_radio_action_get_current_value (selected);
1468
1469         format_state = modest_msg_edit_window_get_format_state (window);
1470         g_return_if_fail (format_state != NULL);
1471
1472         format_state->justification = value;
1473         modest_msg_edit_window_set_format_state (window, format_state);
1474         g_free (format_state);
1475 }
1476
1477 void 
1478 modest_ui_actions_on_select_editor_color (GtkAction *action,
1479                                           ModestMsgEditWindow *window)
1480 {
1481         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1482         g_return_if_fail (GTK_IS_ACTION (action));
1483
1484         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1485                 return;
1486
1487         modest_msg_edit_window_select_color (window);
1488 }
1489
1490 void 
1491 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1492                                                      ModestMsgEditWindow *window)
1493 {
1494         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1495         g_return_if_fail (GTK_IS_ACTION (action));
1496
1497         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1498                 return;
1499
1500         modest_msg_edit_window_select_background_color (window);
1501 }
1502
1503 void 
1504 modest_ui_actions_on_insert_image (GtkAction *action,
1505                                    ModestMsgEditWindow *window)
1506 {
1507         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1508         g_return_if_fail (GTK_IS_ACTION (action));
1509
1510         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1511                 return;
1512
1513         modest_msg_edit_window_insert_image (window);
1514 }
1515
1516 void 
1517 modest_ui_actions_on_attach_file (GtkAction *action,
1518                                   ModestMsgEditWindow *window)
1519 {
1520         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1521         g_return_if_fail (GTK_IS_ACTION (action));
1522
1523         modest_msg_edit_window_attach_file (window);
1524 }
1525
1526 void 
1527 modest_ui_actions_on_remove_attachments (GtkAction *action,
1528                                          ModestMsgEditWindow *window)
1529 {
1530         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1531         g_return_if_fail (GTK_IS_ACTION (action));
1532
1533         modest_msg_edit_window_remove_attachments (window, NULL);
1534 }
1535
1536 /*
1537  * Shows a dialog with an entry that asks for some text. The returned
1538  * value must be freed by the caller. The dialog window title will be
1539  * set to @title.
1540  */
1541 static gchar *
1542 ask_for_folder_name (GtkWindow *parent_window,
1543                      const gchar *title)
1544 {
1545         GtkWidget *dialog, *entry;
1546         gchar *folder_name = NULL;
1547
1548         /* Ask for folder name */
1549         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1550                                               parent_window,
1551                                               GTK_DIALOG_MODAL,
1552                                               GTK_STOCK_CANCEL,
1553                                               GTK_RESPONSE_REJECT,
1554                                               GTK_STOCK_OK,
1555                                               GTK_RESPONSE_ACCEPT,
1556                                               NULL);
1557         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1558                             gtk_label_new(title),
1559                             FALSE, FALSE, 0);
1560                 
1561         entry = gtk_entry_new_with_max_length (40);
1562         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1563                             entry,
1564                             TRUE, FALSE, 0);    
1565         
1566         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1567         
1568         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1569                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1570
1571         gtk_widget_destroy (dialog);
1572
1573         return folder_name;
1574 }
1575
1576 void 
1577 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1578 {
1579         TnyFolderStore *parent_folder;
1580         GtkWidget *folder_view;
1581         
1582         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1583
1584         folder_view = modest_main_window_get_child_widget (main_window,
1585                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1586         if (!folder_view)
1587                 return;
1588
1589         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1590         
1591         if (parent_folder) {
1592                 gboolean finished = FALSE;
1593                 gint result;
1594                 gchar *folder_name = NULL, *suggested_name = NULL;
1595
1596                 /* Run the new folder dialog */
1597                 while (!finished) {
1598                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
1599                                                                         parent_folder,
1600                                                                         suggested_name,
1601                                                                         &folder_name);
1602
1603                         if (result == GTK_RESPONSE_REJECT) {
1604                                 finished = TRUE;
1605                         } else {
1606                                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(main_window));
1607                                 TnyFolder *new_folder = NULL;
1608
1609                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1610                                                                  mail_op);
1611                 
1612                                 new_folder = modest_mail_operation_create_folder (mail_op,
1613                                                                                   parent_folder,
1614                                                                                   (const gchar *) folder_name);
1615                                 if (new_folder) {
1616                                         g_object_unref (new_folder);
1617                                         finished = TRUE;
1618                                 } 
1619 /*                              else { */
1620 /*                                      /\* TODO: check error and follow proper actions *\/ */
1621 /* /\*                                  suggested_name = X; *\/ */
1622 /*                                      /\* Show error to the user *\/ */
1623 /*                                      modest_platform_run_information_dialog (GTK_WINDOW (main_window), */
1624 /*                                                                              _("mail_in_ui_folder_create_error")); */
1625 /*                              } */
1626                                 g_object_unref (mail_op);
1627                         }
1628                         g_free (folder_name);
1629                         folder_name = NULL;
1630                 }
1631
1632                 g_object_unref (parent_folder);
1633         }
1634 }
1635
1636 void 
1637 modest_ui_actions_on_rename_folder (GtkAction *action,
1638                                      ModestMainWindow *main_window)
1639 {
1640         TnyFolderStore *folder;
1641         GtkWidget *folder_view;
1642         GtkWidget *header_view; 
1643
1644         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1645
1646         folder_view = modest_main_window_get_child_widget (main_window,
1647                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1648         if (!folder_view)
1649                 return;
1650
1651         header_view = modest_main_window_get_child_widget (main_window,
1652                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1653         
1654         if (!header_view)
1655                 return;
1656
1657         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1658         
1659         if (folder && TNY_IS_FOLDER (folder)) {
1660                 gchar *folder_name;
1661                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1662                                                    _("Please enter a new name for the folder"));
1663
1664                 if (folder_name != NULL && strlen (folder_name) > 0) {
1665                         ModestMailOperation *mail_op;
1666
1667                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(main_window));
1668                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1669                                                          mail_op);
1670
1671                         modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL);
1672
1673                         modest_mail_operation_rename_folder (mail_op,
1674                                                              TNY_FOLDER (folder),
1675                                                              (const gchar *) folder_name);
1676
1677                         g_object_unref (mail_op);
1678                         g_free (folder_name);
1679                 }
1680                 g_object_unref (folder);
1681         }
1682 }
1683
1684 static void
1685 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1686 {
1687         TnyFolderStore *folder;
1688         GtkWidget *folder_view;
1689         gint response;
1690         gchar *message;
1691         
1692         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1693
1694         folder_view = modest_main_window_get_child_widget (main_window,
1695                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1696         if (!folder_view)
1697                 return;
1698
1699         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1700
1701         /* Show an error if it's an account */
1702         if (!TNY_IS_FOLDER (folder)) {
1703                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1704                                                         _("mail_in_ui_folder_delete_error"));
1705                 return ;
1706         }
1707
1708         /* Ask the user */      
1709         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
1710                                     tny_folder_get_name (TNY_FOLDER (folder)));
1711         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window), 
1712                                                             (const gchar *) message);
1713         g_free (message);
1714
1715         if (response == GTK_RESPONSE_OK) {
1716                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE, G_OBJECT(main_window));
1717
1718                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1719                                                  mail_op);
1720                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1721
1722                 /* Show error if happened */
1723                 if (modest_mail_operation_get_error (mail_op))
1724                         modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1725                                                                 _("mail_in_ui_folder_delete_error"));
1726
1727                 g_object_unref (G_OBJECT (mail_op));
1728         }
1729
1730         g_object_unref (G_OBJECT (folder));
1731 }
1732
1733 void 
1734 modest_ui_actions_on_delete_folder (GtkAction *action,
1735                                      ModestMainWindow *main_window)
1736 {
1737         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1738
1739         delete_folder (main_window, FALSE);
1740 }
1741
1742 void 
1743 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1744 {
1745         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1746         
1747         delete_folder (main_window, TRUE);
1748 }
1749
1750 void
1751 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1752                                          const gchar* server_account_name,
1753                                          gchar **username,
1754                                          gchar **password, 
1755                                          gboolean *cancel, 
1756                                          gboolean *remember,
1757                                          ModestMainWindow *main_window)
1758 {
1759         g_return_if_fail(server_account_name);
1760         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
1761         
1762         /* Initalize output parameters: */
1763         if (cancel)
1764                 *cancel = FALSE;
1765                 
1766         if (remember)
1767                 *remember = TRUE;
1768                 
1769 #ifdef MODEST_PLATFORM_MAEMO
1770         /* Maemo uses a different (awkward) button order,
1771          * It should probably just use gtk_alternative_dialog_button_order ().
1772          */
1773         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1774                                               NULL,
1775                                               GTK_DIALOG_MODAL,
1776                                               GTK_STOCK_OK,
1777                                               GTK_RESPONSE_ACCEPT,
1778                                               GTK_STOCK_CANCEL,
1779                                               GTK_RESPONSE_REJECT,
1780                                               NULL);
1781 #else
1782         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1783                                               NULL,
1784                                               GTK_DIALOG_MODAL,
1785                                               GTK_STOCK_CANCEL,
1786                                               GTK_RESPONSE_REJECT,
1787                                               GTK_STOCK_OK,
1788                                               GTK_RESPONSE_ACCEPT,
1789                                               NULL);
1790 #endif /* MODEST_PLATFORM_MAEMO */
1791
1792         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1793         
1794         gchar *server_name = modest_server_account_get_hostname (
1795                 modest_runtime_get_account_mgr(), server_account_name);
1796         
1797         /* This causes a warning because the logical ID has no %s in it, 
1798          * though the translation does, but there is not much we can do about that: */
1799         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
1800         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1801                             FALSE, FALSE, 0);
1802         g_free (txt);
1803         g_free (server_name);
1804         server_name = NULL;
1805
1806         /* username: */
1807         gchar *initial_username = modest_server_account_get_username (
1808                 modest_runtime_get_account_mgr(), server_account_name);
1809         
1810         GtkWidget *entry_username = gtk_entry_new ();
1811         if (initial_username)
1812                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
1813         /* Dim this if a connection has ever succeeded with this username,
1814          * as per the UI spec: */
1815         const gboolean username_known = 
1816                 modest_server_account_get_username_has_succeeded(
1817                         modest_runtime_get_account_mgr(), server_account_name);
1818         gtk_widget_set_sensitive (entry_username, !username_known);
1819         
1820 #ifdef MODEST_PLATFORM_MAEMO
1821         /* Auto-capitalization is the default, so let's turn it off: */
1822         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
1823         
1824         /* Create a size group to be used by all captions.
1825          * Note that HildonCaption does not create a default size group if we do not specify one.
1826          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
1827         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1828         
1829         GtkWidget *caption = hildon_caption_new (sizegroup, 
1830                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
1831         gtk_widget_show (entry_username);
1832         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1833                 FALSE, FALSE, MODEST_MARGIN_HALF);
1834         gtk_widget_show (caption);
1835 #else 
1836         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
1837                             TRUE, FALSE, 0);
1838 #endif /* MODEST_PLATFORM_MAEMO */      
1839                             
1840         /* password: */
1841         GtkWidget *entry_password = gtk_entry_new ();
1842         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
1843         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
1844         
1845 #ifdef MODEST_PLATFORM_MAEMO
1846         /* Auto-capitalization is the default, so let's turn it off: */
1847         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
1848                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
1849         
1850         caption = hildon_caption_new (sizegroup, 
1851                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
1852         gtk_widget_show (entry_password);
1853         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1854                 FALSE, FALSE, MODEST_MARGIN_HALF);
1855         gtk_widget_show (caption);
1856         g_object_unref (sizegroup);
1857 #else 
1858         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
1859                             TRUE, FALSE, 0);
1860 #endif /* MODEST_PLATFORM_MAEMO */      
1861                                 
1862 /* This is not in the Maemo UI spec:
1863         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1864         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1865                             TRUE, FALSE, 0);
1866 */
1867
1868         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1869         
1870         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1871                 if (username) {
1872                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
1873                         
1874                         modest_server_account_set_username (
1875                                  modest_runtime_get_account_mgr(), server_account_name, 
1876                                  *username);
1877                                  
1878                         const gboolean username_was_changed = 
1879                                 (strcmp (*username, initial_username) != 0);
1880                         if (username_was_changed) {
1881                                 /* To actually use a changed username, 
1882                                  * we must reset the connection, according to pvanhoof.
1883                                  * This _might_ be a sensible way to do that: */
1884                                  TnyDevice *device = modest_runtime_get_device();
1885                                  tny_device_force_offline (device);
1886                                  tny_device_force_online (device);
1887                         }
1888                 }
1889                         
1890                 if (password) {
1891                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
1892                         
1893                         /* We do not save the password in the configuration, 
1894                          * because this function is only called for passwords that should 
1895                          * not be remembered:
1896                         modest_server_account_set_password (
1897                                  modest_runtime_get_account_mgr(), server_account_name, 
1898                                  *password);
1899                         */
1900                 }
1901                 
1902                 if (cancel)
1903                         *cancel   = FALSE;
1904                         
1905         } else {
1906                 if (username)
1907                         *username = NULL;
1908                         
1909                 if (password)
1910                         *password = NULL;
1911                         
1912                 if (cancel)
1913                         *cancel   = TRUE;
1914         }
1915
1916 /* This is not in the Maemo UI spec:
1917         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1918                 *remember = TRUE;
1919         else
1920                 *remember = FALSE;
1921 */
1922
1923         gtk_widget_destroy (dialog);
1924         
1925         printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel);
1926 }
1927
1928 void
1929 modest_ui_actions_on_cut (GtkAction *action,
1930                           ModestWindow *window)
1931 {
1932         GtkWidget *focused_widget;
1933
1934         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1935         if (GTK_IS_EDITABLE (focused_widget)) {
1936                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1937         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1938                 GtkTextBuffer *buffer;
1939                 GtkClipboard *clipboard;
1940
1941                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1942                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1943                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1944         }
1945 }
1946
1947 void
1948 modest_ui_actions_on_copy (GtkAction *action,
1949                            ModestWindow *window)
1950 {
1951         GtkClipboard *clipboard;
1952         GtkWidget *focused_widget;
1953
1954         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1955         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1956         if (GTK_IS_LABEL (focused_widget)) {
1957                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1958         } else if (GTK_IS_EDITABLE (focused_widget)) {
1959                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1960         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1961                 GtkTextBuffer *buffer;
1962
1963                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1964                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1965         }
1966 }
1967
1968 void
1969 modest_ui_actions_on_undo (GtkAction *action,
1970                            ModestWindow *window)
1971 {
1972         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
1973                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
1974         } else {
1975                 g_return_if_reached ();
1976         }
1977 }
1978
1979 void
1980 modest_ui_actions_on_paste (GtkAction *action,
1981                             ModestWindow *window)
1982 {
1983         GtkWidget *focused_widget;
1984
1985         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1986         if (GTK_IS_EDITABLE (focused_widget)) {
1987                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1988         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1989                 GtkTextBuffer *buffer;
1990                 GtkClipboard *clipboard;
1991
1992                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1993                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1994                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1995         }
1996 }
1997
1998 void
1999 modest_ui_actions_on_select_all (GtkAction *action,
2000                                  ModestWindow *window)
2001 {
2002         GtkWidget *focused_widget;
2003
2004         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2005         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2006                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2007         } else if (GTK_IS_LABEL (focused_widget)) {
2008                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2009         } else if (GTK_IS_EDITABLE (focused_widget)) {
2010                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2011         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2012                 GtkTextBuffer *buffer;
2013                 GtkTextIter start, end;
2014
2015                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2016                 gtk_text_buffer_get_start_iter (buffer, &start);
2017                 gtk_text_buffer_get_end_iter (buffer, &end);
2018                 gtk_text_buffer_select_range (buffer, &start, &end);
2019         }
2020 }
2021
2022 void
2023 modest_ui_actions_on_mark_as_read (GtkAction *action,
2024                                    ModestWindow *window)
2025 {       
2026         g_return_if_fail (MODEST_IS_WINDOW(window));
2027                 
2028         /* Mark each header as read */
2029         do_headers_action (window, headers_action_mark_as_read, NULL);
2030 }
2031
2032 void
2033 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2034                                      ModestWindow *window)
2035 {       
2036         g_return_if_fail (MODEST_IS_WINDOW(window));
2037                 
2038         /* Mark each header as read */
2039         do_headers_action (window, headers_action_mark_as_unread, NULL);
2040 }
2041
2042 void
2043 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2044                                   GtkRadioAction *selected,
2045                                   ModestWindow *window)
2046 {
2047         gint value;
2048
2049         value = gtk_radio_action_get_current_value (selected);
2050         if (MODEST_IS_WINDOW (window)) {
2051                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2052         }
2053 }
2054
2055 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2056                                                         GtkRadioAction *selected,
2057                                                         ModestWindow *window)
2058 {
2059         TnyHeaderFlags flags;
2060         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2061
2062         flags = gtk_radio_action_get_current_value (selected);
2063         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2064 }
2065
2066 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2067                                                            GtkRadioAction *selected,
2068                                                            ModestWindow *window)
2069 {
2070         gint file_format;
2071
2072         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2073
2074         file_format = gtk_radio_action_get_current_value (selected);
2075         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2076 }
2077
2078
2079 void     
2080 modest_ui_actions_on_zoom_plus (GtkAction *action,
2081                                 ModestWindow *window)
2082 {
2083         g_return_if_fail (MODEST_IS_WINDOW (window));
2084
2085         modest_window_zoom_plus (MODEST_WINDOW (window));
2086 }
2087
2088 void     
2089 modest_ui_actions_on_zoom_minus (GtkAction *action,
2090                                  ModestWindow *window)
2091 {
2092         g_return_if_fail (MODEST_IS_WINDOW (window));
2093
2094         modest_window_zoom_minus (MODEST_WINDOW (window));
2095 }
2096
2097 void     
2098 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2099                                            ModestWindow *window)
2100 {
2101         ModestWindowMgr *mgr;
2102         gboolean fullscreen, active;
2103         g_return_if_fail (MODEST_IS_WINDOW (window));
2104
2105         mgr = modest_runtime_get_window_mgr ();
2106
2107         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2108         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2109
2110         if (active != fullscreen) {
2111                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2112                 gtk_window_present (GTK_WINDOW (window));
2113         }
2114 }
2115
2116 void
2117 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2118                                         ModestWindow *window)
2119 {
2120         ModestWindowMgr *mgr;
2121         gboolean fullscreen;
2122
2123         g_return_if_fail (MODEST_IS_WINDOW (window));
2124
2125         mgr = modest_runtime_get_window_mgr ();
2126         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2127         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2128
2129         gtk_window_present (GTK_WINDOW (window));
2130 }
2131
2132 /* 
2133  * Used by modest_ui_actions_on_details to call do_headers_action 
2134  */
2135 static void
2136 headers_action_show_details (TnyHeader *header, 
2137                              ModestWindow *window,
2138                              gpointer user_data)
2139
2140 {
2141         GtkWidget *dialog;
2142         
2143         /* Create dialog */
2144         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2145
2146         /* Run dialog */
2147         gtk_widget_show_all (dialog);
2148         gtk_dialog_run (GTK_DIALOG (dialog));
2149
2150         gtk_widget_destroy (dialog);
2151 }
2152
2153 /*
2154  * Show the folder details in a ModestDetailsDialog widget
2155  */
2156 static void
2157 show_folder_details (TnyFolder *folder, 
2158                      GtkWindow *window)
2159 {
2160         GtkWidget *dialog;
2161         
2162         /* Create dialog */
2163         dialog = modest_details_dialog_new_with_folder (window, folder);
2164
2165         /* Run dialog */
2166         gtk_widget_show_all (dialog);
2167         gtk_dialog_run (GTK_DIALOG (dialog));
2168
2169         gtk_widget_destroy (dialog);
2170 }
2171
2172 /*
2173  * Show the header details in a ModestDetailsDialog widget
2174  */
2175 void     
2176 modest_ui_actions_on_details (GtkAction *action, 
2177                               ModestWindow *win)
2178 {
2179         TnyList * headers_list;
2180         TnyIterator *iter;
2181         TnyHeader *header;              
2182
2183         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2184                 TnyMsg *msg;
2185
2186                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2187                 if (!msg)
2188                         return;
2189                 g_object_unref (msg);           
2190
2191                 headers_list = get_selected_headers (win);
2192                 if (!headers_list)
2193                         return;
2194
2195                 iter = tny_list_create_iterator (headers_list);
2196
2197                 header = TNY_HEADER (tny_iterator_get_current (iter));
2198                 headers_action_show_details (header, win, NULL);
2199                 g_object_unref (header);
2200
2201                 g_object_unref (iter);
2202                 g_object_unref (headers_list);
2203
2204         } else if (MODEST_IS_MAIN_WINDOW (win)) {
2205                 GtkWidget *folder_view, *header_view;
2206
2207                 /* Check which widget has the focus */
2208                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2209                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
2210                 if (gtk_widget_is_focus (folder_view)) {
2211                         TnyFolder *folder;
2212
2213                         folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2214
2215                         /* Show only when it's a folder */
2216                         if (!folder || !TNY_IS_FOLDER (folder))
2217                                 return;
2218
2219                         show_folder_details (folder, GTK_WINDOW (win));
2220
2221                 } else {
2222                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2223                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2224                         /* Show details of each header */
2225                         do_headers_action (win, headers_action_show_details, header_view);
2226                 }
2227         }
2228 }
2229
2230 void     
2231 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
2232                                      ModestMsgEditWindow *window)
2233 {
2234         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2235
2236         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
2237 }
2238
2239 void     
2240 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
2241                                       ModestMsgEditWindow *window)
2242 {
2243         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2244
2245         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
2246 }
2247
2248 void
2249 modest_ui_actions_toggle_folders_view (GtkAction *action, 
2250                                        ModestMainWindow *main_window)
2251 {
2252         ModestConf *conf;
2253         
2254         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2255
2256         conf = modest_runtime_get_conf ();
2257         
2258         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
2259                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
2260         else
2261                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
2262 }
2263
2264 void 
2265 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
2266                                      ModestWindow *window)
2267 {
2268         gboolean active, fullscreen = FALSE;
2269         ModestWindowMgr *mgr;
2270
2271         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
2272
2273         /* Check if we want to toggle the toolbar vuew in fullscreen
2274            or normal mode */
2275         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
2276                      "ViewShowToolbarFullScreen")) {
2277                 fullscreen = TRUE;
2278         }
2279
2280         /* Toggle toolbar */
2281         mgr = modest_runtime_get_window_mgr ();
2282         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
2283 }
2284
2285 void     
2286 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
2287                                            ModestMsgEditWindow *window)
2288 {
2289         modest_msg_edit_window_select_font (window);
2290 }
2291
2292 void
2293 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
2294                                                   const gchar *display_name,
2295                                                   GtkWindow *window)
2296 {
2297         /* Do not change the application name if the widget has not
2298            the focus. This callback could be called even if the folder
2299            view has not the focus, because the handled signal could be
2300            emitted when the folder view is redrawn */
2301         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
2302                 if (display_name)
2303                         gtk_window_set_title (window, display_name);
2304                 else
2305                         gtk_window_set_title (window, " ");
2306         }
2307 }
2308
2309 void
2310 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2311 {
2312         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2313         modest_msg_edit_window_select_contacts (window);
2314 }
2315
2316 void
2317 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2318 {
2319         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2320         modest_msg_edit_window_check_names (window);
2321 }
2322
2323
2324 static GtkWidget*
2325 create_move_to_dialog (ModestWindow *win,
2326                        GtkWidget *folder_view,
2327                        GtkWidget **tree_view)
2328 {
2329         GtkWidget *dialog, *scroll;
2330
2331         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2332                                               GTK_WINDOW (win),
2333                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2334                                               GTK_STOCK_OK,
2335                                               GTK_RESPONSE_ACCEPT,
2336                                               GTK_STOCK_CANCEL,
2337                                               GTK_RESPONSE_REJECT,
2338                                               NULL);
2339
2340         /* Create scrolled window */
2341         scroll = gtk_scrolled_window_new (NULL, NULL);
2342         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
2343                                          GTK_POLICY_AUTOMATIC,
2344                                          GTK_POLICY_AUTOMATIC);
2345
2346         /* Create folder view */
2347         *tree_view = modest_folder_view_new (NULL);
2348         gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2349                                  gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2350         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2351
2352         /* Add scroll to dialog */
2353         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
2354                             scroll, FALSE, FALSE, 0);
2355
2356         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2357
2358         return dialog;
2359 }
2360
2361 /*
2362  * Returns TRUE if at least one of the headers of the list belongs to
2363  * a message that has been fully retrieved.
2364  */
2365 static gboolean
2366 has_retrieved_msgs (TnyList *list)
2367 {
2368         TnyIterator *iter;
2369         gboolean found = FALSE;
2370
2371         iter = tny_list_create_iterator (list);
2372         while (tny_iterator_is_done (iter) && !found) {
2373                 TnyHeader *header;
2374                 TnyHeaderFlags flags;
2375
2376                 header = TNY_HEADER (tny_iterator_get_current (iter));
2377                 flags = tny_header_get_flags (header);
2378                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2379                         found = TRUE;
2380
2381                 if (!found)
2382                         tny_iterator_next (iter);
2383         }
2384         g_object_unref (iter);
2385
2386         return found;
2387 }
2388
2389 /*
2390  * Shows a confirmation dialog to the user when we're moving messages
2391  * from a remote server to the local storage. Returns the dialog
2392  * response. If it's other kind of movement the it always returns
2393  * GTK_RESPONSE_OK
2394  */
2395 static gint
2396 msgs_move_to_confirmation (GtkWindow *win,
2397                            TnyFolder *dest_folder,
2398                            TnyList *headers)
2399 {
2400         gint response = GTK_RESPONSE_OK;
2401
2402         /* If the destination is a local folder */
2403         if (modest_tny_folder_is_local_folder (dest_folder)) {
2404                 TnyFolder *src_folder;
2405                 TnyIterator *iter;
2406                 TnyHeader *header;
2407
2408                 /* Get source folder */
2409                 iter = tny_list_create_iterator (headers);
2410                 header = TNY_HEADER (tny_iterator_get_current (iter));
2411                 src_folder = tny_header_get_folder (header);
2412                 g_object_unref (header);
2413                 g_object_unref (iter);
2414
2415                 /* If the source is a remote folder */
2416                 if (!modest_tny_folder_is_local_folder (src_folder)) {
2417                         const gchar *message;
2418                         
2419                         if (tny_list_get_length (headers) == 1)
2420                                 if (has_retrieved_msgs (headers))
2421                                         message = _("mcen_nc_move_retrieve");
2422                                 else
2423                                         message = _("mcen_nc_move_header");
2424                         else
2425                                 if (has_retrieved_msgs (headers))
2426                                         message = _("mcen_nc_move_retrieves");
2427                                 else
2428                                         message = _("mcen_nc_move_headers");
2429                         
2430                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2431                                                                             (const gchar *) message);
2432                 }
2433                 g_object_unref (src_folder);
2434         }
2435         return response;
2436 }
2437
2438
2439 static void
2440 tranasfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
2441 {
2442         ModestMsgViewWindow *self = NULL;
2443         gboolean found = FALSE;
2444
2445         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
2446         self = MODEST_MSG_VIEW_WINDOW (object);
2447
2448         found = modest_msg_view_window_select_first_message (self);
2449         g_return_if_fail (found);
2450 }
2451
2452 static void
2453 move_to_error_checking (const GObject *obj, gpointer user_data)
2454 {
2455         ModestWindow *win = NULL;
2456         
2457         g_return_if_fail (MODEST_IS_WINDOW (obj));
2458         win = MODEST_WINDOW (obj);
2459
2460         /* TODO: show error message */
2461 /*      modest_platform_run_information_dialog (GTK_WINDOW (win), */
2462 /*                                              _("mail_in_ui_folder_move_target_error")); */
2463 }
2464
2465 /*
2466  * UI handler for the "Move to" action when invoked from the
2467  * ModestMainWindow
2468  */
2469 static void 
2470 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
2471                                           ModestMainWindow *win)
2472 {
2473         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
2474         GtkWidget *header_view = NULL;
2475         gint result;
2476         TnyFolderStore *folder_store = NULL;
2477         ModestMailOperation *mail_op = NULL;
2478
2479         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2480
2481         /* Get the folder view */
2482         folder_view = modest_main_window_get_child_widget (win,
2483                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2484
2485         /* Get header view */
2486         header_view = modest_main_window_get_child_widget (win,
2487                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2488
2489         /* Create and run the dialog */
2490         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2491         result = gtk_dialog_run (GTK_DIALOG(dialog));
2492         g_object_ref (tree_view);
2493
2494         /* We do this to save an indentation level ;-) */
2495         if (result != GTK_RESPONSE_ACCEPT)
2496                 goto end;
2497
2498         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2499
2500         if (TNY_IS_ACCOUNT (folder_store))
2501                 goto end;
2502
2503         /* Get folder or messages to transfer */
2504         if (gtk_widget_is_focus (folder_view)) {
2505                 TnyFolderStore *src_folder;
2506                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2507
2508                 /* Clean folder on header view before moving it */
2509                 modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL); 
2510
2511                 if (TNY_IS_FOLDER (src_folder)) {
2512                         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_ID_RECEIVE, 
2513                                                                                  G_OBJECT(win),
2514                                                                                  move_to_error_checking);
2515                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2516                                                          mail_op);
2517
2518                         modest_mail_operation_xfer_folder (mail_op, 
2519                                                            TNY_FOLDER (src_folder),
2520                                                            folder_store,
2521                                                            TRUE);
2522                         g_object_unref (G_OBJECT (mail_op));
2523                         
2524                 }
2525
2526                 /* Frees */
2527                 g_object_unref (G_OBJECT (src_folder));
2528         } else {
2529                 if (gtk_widget_is_focus (header_view)) {
2530                         TnyList *headers;
2531                         gint response;
2532
2533                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2534
2535                         /* Ask for user confirmation */
2536                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2537                                                               TNY_FOLDER (folder_store), 
2538                                                               headers);
2539
2540                         /* Transfer messages */
2541                         if (response == GTK_RESPONSE_OK) {
2542                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2543                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2544                                                                  mail_op);
2545
2546                                 modest_mail_operation_xfer_msgs (mail_op, 
2547                                                                  headers,
2548                                                                  TNY_FOLDER (folder_store),
2549                                                                  TRUE,
2550                                                                  NULL,
2551                                                                  NULL);
2552                                 g_object_unref (G_OBJECT (mail_op));
2553                         }
2554                         g_object_unref (headers);
2555                 }
2556         }
2557         g_object_unref (folder_store);
2558         
2559  end:
2560         gtk_widget_destroy (dialog);
2561 }
2562
2563
2564 /*
2565  * UI handler for the "Move to" action when invoked from the
2566  * ModestMsgViewWindow
2567  */
2568 static void 
2569 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
2570                                               ModestMsgViewWindow *win)
2571 {
2572         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2573         gint result;
2574         ModestMainWindow *main_window;
2575         TnyHeader *header;
2576         TnyList *headers;
2577
2578         /* Get the folder view */
2579         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2580         folder_view = modest_main_window_get_child_widget (main_window,
2581                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2582
2583         /* Create and run the dialog */
2584         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
2585         result = gtk_dialog_run (GTK_DIALOG(dialog));
2586         g_object_ref (tree_view);
2587
2588         if (result == GTK_RESPONSE_ACCEPT) {
2589                 TnyFolderStore *folder_store;
2590                 gint response;
2591
2592                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2593
2594                 /* Create header list */
2595                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
2596                 headers = tny_simple_list_new ();
2597                 tny_list_prepend (headers, G_OBJECT (header));
2598                 g_object_unref (header);
2599
2600                 /* Ask user for confirmation. MSG-NOT404 */
2601                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2602                                                       TNY_FOLDER (folder_store), 
2603                                                       headers);
2604
2605                 /* Transfer current msg */
2606                 if (response == GTK_RESPONSE_OK) {
2607                         ModestMailOperation *mail_op;
2608
2609                         /* Create mail op */
2610                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2611                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2612                                                          mail_op);
2613                         
2614                         /* Transfer messages */
2615                         modest_mail_operation_xfer_msgs (mail_op, 
2616                                                          headers,
2617                                                          TNY_FOLDER (folder_store),
2618                                                          TRUE,
2619                                                          tranasfer_msgs_from_viewer_cb,
2620                                                          NULL);
2621                         g_object_unref (G_OBJECT (mail_op));
2622                 } 
2623                 g_object_unref (headers);
2624                 g_object_unref (folder_store);
2625         }
2626         gtk_widget_destroy (dialog);
2627 }
2628
2629 void 
2630 modest_ui_actions_on_move_to (GtkAction *action, 
2631                               ModestWindow *win)
2632 {
2633         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
2634                           MODEST_IS_MSG_VIEW_WINDOW (win));
2635
2636         if (MODEST_IS_MAIN_WINDOW (win)) 
2637                 modest_ui_actions_on_main_window_move_to (action, 
2638                                                           MODEST_MAIN_WINDOW (win));
2639         else
2640                 modest_ui_actions_on_msg_view_window_move_to (action, 
2641                                                               MODEST_MSG_VIEW_WINDOW (win));
2642 }
2643
2644 /*
2645  * Calls #HeadersFunc for each header already selected in the main
2646  * window or the message currently being shown in the msg view window
2647  */
2648 static void
2649 do_headers_action (ModestWindow *win, 
2650                    HeadersFunc func,
2651                    gpointer user_data)
2652 {
2653         TnyList *headers_list;
2654         TnyIterator *iter;
2655
2656         /* Get headers */
2657         headers_list = get_selected_headers (win);
2658         if (!headers_list)
2659                 return;
2660
2661         /* Call the function for each header */
2662         iter = tny_list_create_iterator (headers_list);
2663         while (!tny_iterator_is_done (iter)) {
2664                 TnyHeader *header;
2665
2666                 header = TNY_HEADER (tny_iterator_get_current (iter));
2667                 func (header, win, user_data);
2668                 g_object_unref (header);
2669                 tny_iterator_next (iter);
2670         }
2671         g_object_unref (iter);
2672         g_object_unref (headers_list);
2673 }
2674
2675 void 
2676 modest_ui_actions_view_attachment (GtkAction *action,
2677                                    ModestWindow *window)
2678 {
2679         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2680                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
2681         } else {
2682                 /* not supported window for this action */
2683                 g_return_if_reached ();
2684         }
2685 }
2686
2687 void
2688 modest_ui_actions_save_attachments (GtkAction *action,
2689                                     ModestWindow *window)
2690 {
2691         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2692                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2693         } else {
2694                 /* not supported window for this action */
2695                 g_return_if_reached ();
2696         }
2697 }
2698
2699 void
2700 modest_ui_actions_remove_attachments (GtkAction *action,
2701                                       ModestWindow *window)
2702 {
2703         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2704                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2705         } else {
2706                 /* not supported window for this action */
2707                 g_return_if_reached ();
2708         }
2709 }
2710
2711 void 
2712 modest_ui_actions_on_settings (GtkAction *action, 
2713                                ModestWindow *win)
2714 {
2715         GtkWidget *dialog;
2716
2717         dialog = modest_platform_get_global_settings_dialog ();
2718         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
2719         gtk_widget_show (dialog);
2720
2721         gtk_dialog_run (GTK_DIALOG (dialog));
2722
2723         gtk_widget_destroy (dialog);
2724 }
2725
2726 void 
2727 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
2728                                             ModestWindow *window)
2729 {
2730         ModestMailOperation *mail_op;
2731         TnyList *headers;
2732
2733         /* Get headers */
2734         headers = get_selected_headers (window);
2735         if (!headers)
2736                 return;
2737
2738         /* Create mail operation */
2739         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT (window));
2740         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2741         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
2742
2743         /* Frees */
2744         g_object_unref (headers);
2745         g_object_unref (mail_op);
2746 }