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