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