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