* src/modest-ui-actions.c:
[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 <glib/gprintf.h>
36 #include <string.h>
37 #include <modest-runtime.h>
38 #include <modest-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
44
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include <tny-mime-part.h>
48
49 #ifdef MODEST_PLATFORM_MAEMO
50 #include "maemo/modest-osso-state-saving.h"
51 #include "maemo/modest-maemo-utils.h"
52 #include "maemo/modest-hildon-includes.h"
53 #endif /* MODEST_PLATFORM_MAEMO */
54
55 #include "widgets/modest-ui-constants.h"
56 #include <widgets/modest-main-window.h>
57 #include <widgets/modest-msg-view-window.h>
58 #include <widgets/modest-account-view-window.h>
59 #include <widgets/modest-details-dialog.h>
60 #include <widgets/modest-attachments-view.h>
61 #include "widgets/modest-folder-view.h"
62 #include "widgets/modest-global-settings-dialog.h"
63 #include "modest-connection-specific-smtp-window.h"
64 #include "modest-account-mgr-helpers.h"
65 #include "modest-mail-operation.h"
66 #include "modest-text-utils.h"
67
68 #ifdef MODEST_HAVE_EASYSETUP
69 #include "easysetup/modest-easysetup-wizard.h"
70 #endif /* MODEST_HAVE_EASYSETUP */
71
72 #include <modest-widget-memory.h>
73 #include <tny-error.h>
74 #include <tny-simple-list.h>
75 #include <tny-msg-view.h>
76 #include <tny-device.h>
77 #include <tny-merge-folder.h>
78
79 #include <gtkhtml/gtkhtml.h>
80
81 typedef struct _GetMsgAsyncHelper {     
82         ModestWindow *window;
83         ModestMailOperation *mail_op;
84         TnyIterator *iter;
85         guint num_ops;
86         GFunc func;     
87         gpointer user_data;
88 } GetMsgAsyncHelper;
89
90 typedef enum _ReplyForwardAction {
91         ACTION_REPLY,
92         ACTION_REPLY_TO_ALL,
93         ACTION_FORWARD
94 } ReplyForwardAction;
95
96 typedef struct _ReplyForwardHelper {
97         guint reply_forward_type;
98         ReplyForwardAction action;
99         gchar *account_name;
100         GtkWidget *parent_window;
101 } ReplyForwardHelper;
102
103 typedef struct _PasteAsAttachmentHelper {
104         ModestMsgEditWindow *window;
105         GtkWidget *banner;
106 } PasteAsAttachmentHelper;
107
108
109 /*
110  * The do_headers_action uses this kind of functions to perform some
111  * action to each member of a list of headers
112  */
113 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
114
115 static void     do_headers_action     (ModestWindow *win, 
116                                        HeadersFunc func,
117                                        gpointer user_data);
118
119 static void     open_msg_cb            (ModestMailOperation *mail_op, 
120                                         TnyHeader *header, 
121                                         TnyMsg *msg,
122                                         gpointer user_data);
123
124 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
125                                         TnyHeader *header, 
126                                         TnyMsg *msg,
127                                         gpointer user_data);
128
129 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
130
131 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
132                                         TnyFolder *folder, 
133                                         gpointer user_data);
134
135 static void     _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
136                                                    ModestMailOperationState *state,
137                                                    gpointer user_data);
138
139 static gboolean
140 download_uncached_messages (TnyList *header_list, GtkWindow *win,
141                             gboolean reply_fwd);
142
143
144 static void
145 run_account_setup_wizard (ModestWindow *win)
146 {
147         ModestEasysetupWizardDialog *wizard;
148
149         g_return_if_fail (MODEST_IS_WINDOW(win));
150         
151         wizard = modest_easysetup_wizard_dialog_new ();
152         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
153         gtk_dialog_run (GTK_DIALOG (wizard));
154         gtk_widget_destroy (GTK_WIDGET (wizard));
155 }
156
157
158 void   
159 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
160 {
161         GtkWidget *about;
162         const gchar *authors[] = {
163                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
164                 NULL
165         };
166         about = gtk_about_dialog_new ();
167         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
168         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
169         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
170                                         _("Copyright (c) 2006, Nokia Corporation\n"
171                                           "All rights reserved."));
172         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
173                                        _("a modest e-mail client\n\n"
174                                          "design and implementation: Dirk-Jan C. Binnema\n"
175                                          "contributions from the fine people at KC and Ig\n"
176                                          "uses the tinymail email framework written by Philip van Hoof"));
177         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
178         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
179         
180         gtk_dialog_run (GTK_DIALOG (about));
181         gtk_widget_destroy(about);
182 }
183
184 /*
185  * Gets the list of currently selected messages. If the win is the
186  * main window, then it returns a newly allocated list of the headers
187  * selected in the header view. If win is the msg view window, then
188  * the value returned is a list with just a single header.
189  *
190  * The caller of this funcion must free the list.
191  */
192 static TnyList *
193 get_selected_headers (ModestWindow *win)
194 {
195         if (MODEST_IS_MAIN_WINDOW(win)) {
196                 GtkWidget *header_view;         
197                 
198                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
199                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
200                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
201                 
202         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
203                 /* for MsgViewWindows, we simply return a list with one element */
204                 TnyHeader *header;
205                 TnyList *list = NULL;
206                 
207                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
208                 if (header != NULL) {
209                         list = tny_simple_list_new ();
210                         tny_list_prepend (list, G_OBJECT(header));
211                         g_object_unref (G_OBJECT(header));
212                 }
213
214                 return list;
215
216         } else
217                 return NULL;
218 }
219
220 static void
221 headers_action_mark_as_read (TnyHeader *header,
222                              ModestWindow *win,
223                              gpointer user_data)
224 {
225         TnyHeaderFlags flags;
226
227         g_return_if_fail (TNY_IS_HEADER(header));
228
229         flags = tny_header_get_flags (header);
230         if (flags & TNY_HEADER_FLAG_SEEN) return;
231         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
232 }
233
234 static void
235 headers_action_mark_as_unread (TnyHeader *header,
236                                ModestWindow *win,
237                                gpointer user_data)
238 {
239         TnyHeaderFlags flags;
240
241         g_return_if_fail (TNY_IS_HEADER(header));
242
243         flags = tny_header_get_flags (header);
244         if (flags & TNY_HEADER_FLAG_SEEN)  {
245                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
246         }
247 }
248
249 /** A convenience method, because deleting a message is 
250  * otherwise complicated, and it's best to change it in one place 
251  * when we change it.
252  */
253 void modest_do_message_delete (TnyHeader *header, ModestWindow *win)
254 {
255         ModestMailOperation *mail_op = NULL;
256         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, 
257                 win ? G_OBJECT(win) : NULL);
258         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
259                                          mail_op);
260         
261         /* Always delete. TODO: Move to trash still not supported */
262         modest_mail_operation_remove_msg (mail_op, header, FALSE);
263         g_object_unref (G_OBJECT (mail_op));
264 }
265
266 static void
267 headers_action_delete (TnyHeader *header,
268                        ModestWindow *win,
269                        gpointer user_data)
270 {
271         modest_do_message_delete (header, win);
272
273 /* refilter treemodel to hide marked-as-deleted rows */
274 /*      if (MODEST_IS_HEADER_VIEW (user_data)) */
275 /*              modest_header_view_refilter (MODEST_HEADER_VIEW (user_data)); */
276 }
277
278 /** After deleing a message that is currently visible in a window, 
279  * show the next message from the list, or close the window if there are no more messages.
280  **/
281 void modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
282 {
283         /* Close msg view window or select next */
284         if (modest_msg_view_window_last_message_selected (win) &&
285                 modest_msg_view_window_first_message_selected (win)) {
286                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
287         } else {
288                 modest_msg_view_window_select_next_message (win);
289         }
290 }
291
292 void
293 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
294 {
295         TnyList *header_list = NULL;
296         TnyIterator *iter = NULL;
297         TnyHeader *header = NULL;
298         gchar *message = NULL;
299         gchar *desc = NULL;
300         gint response;
301         ModestWindowMgr *mgr;
302         GtkWidget *header_view = NULL;
303
304         g_return_if_fail (MODEST_IS_WINDOW(win));
305         
306         /* Check first if the header view has the focus */
307         if (MODEST_IS_MAIN_WINDOW (win)) {
308                 header_view = 
309                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
310                                                              MODEST_WIDGET_TYPE_HEADER_VIEW);
311                 if (!gtk_widget_is_focus (header_view))
312                         return;
313         }
314         
315         header_list = get_selected_headers (win);
316         if (!header_list) return;
317
318         /* Check if any of the headers are already opened, or in the process of being opened */
319         if (MODEST_IS_MAIN_WINDOW (win)) {
320                 gboolean found;
321                 iter = tny_list_create_iterator (header_list);
322                 found = FALSE;
323                 mgr = modest_runtime_get_window_mgr ();
324                 while (!tny_iterator_is_done (iter) && !found) {
325                         header = TNY_HEADER (tny_iterator_get_current (iter));
326                         if (header) {
327                                 found =  modest_window_mgr_find_registered_header (mgr, header, NULL);
328                                 g_object_unref (header);
329                         }
330
331                         tny_iterator_next (iter);
332                 }
333                 g_object_unref (iter);
334
335                 if (found) {
336                         gchar *num, *msg;
337
338                         num = g_strdup_printf ("%d", tny_list_get_length (header_list));
339                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), num);
340
341                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
342                         
343                         g_free (msg);
344                         g_free (num);
345                         g_object_unref (header_list);
346                         return;
347                 }
348         }
349
350         /* Select message */
351         if (tny_list_get_length(header_list) == 1) {
352                 iter = tny_list_create_iterator (header_list);
353                 header = TNY_HEADER (tny_iterator_get_current (iter));
354                 if (header) {
355                         desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
356                         g_object_unref (header);
357                 }
358
359                 g_object_unref (iter);
360         }
361         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
362                                            tny_list_get_length(header_list)), desc);
363
364         /* Confirmation dialog */
365         printf("DEBUG: %s\n", __FUNCTION__);    
366         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
367                                                             message);
368         
369
370         if (response == GTK_RESPONSE_OK) {      
371                 ModestWindow *main_window = NULL;
372                 ModestWindowMgr *mgr = NULL;
373                 GtkTreeModel *model = NULL;
374                 GtkTreeSelection *sel = NULL;
375                 GList *sel_list = NULL, *tmp = NULL;
376                 GtkTreeRowReference *row_reference = NULL;
377                 GtkTreePath *next_path = NULL;
378
379                 /* Find last selected row */                    
380                 if (MODEST_IS_MAIN_WINDOW (win)) {
381                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
382                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
383                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
384                         for (tmp=sel_list; tmp; tmp=tmp->next) {
385                                 if (tmp->next == NULL) {
386                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
387                                         gtk_tree_path_next (next_path);
388                                         row_reference = gtk_tree_row_reference_new (model, next_path);
389                                         gtk_tree_path_free (next_path);
390                                 }
391                         }
392                 }
393                 
394                 /* Remove each header. If it's a view window header_view == NULL */
395                 do_headers_action (win, headers_action_delete, header_view);
396
397                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
398                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
399                         
400                         /* Get main window */
401                         mgr = modest_runtime_get_window_mgr ();
402                         main_window = modest_window_mgr_get_main_window (mgr);
403                 }
404                 else {                  
405                         /* Move cursor to next row */
406                         main_window = win; 
407
408                         /* Select next row */
409                         if (gtk_tree_row_reference_valid (row_reference)) {
410                                 next_path = gtk_tree_row_reference_get_path (row_reference);
411                                 gtk_tree_selection_select_path (sel, next_path);
412                                 gtk_tree_path_free (next_path);
413                         }
414                         if (row_reference != NULL)
415                                 gtk_tree_row_reference_free (row_reference);
416                 }
417
418                 /* Update toolbar dimming state */
419                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
420
421                 /* Free */
422                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
423                 g_list_free (sel_list);
424         }
425
426         /* Free*/
427         g_free(message);
428         g_free(desc);
429         g_object_unref (header_list);
430 }
431
432
433
434
435 /* delete either message or folder, based on where we are */
436 void
437 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
438 {
439         g_return_if_fail (MODEST_IS_WINDOW(win));
440         
441         /* Check first if the header view has the focus */
442         if (MODEST_IS_MAIN_WINDOW (win)) {
443                 GtkWidget *w;
444                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
445                                                          MODEST_WIDGET_TYPE_FOLDER_VIEW);
446                 if (gtk_widget_is_focus (w)) {
447                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
448                         return;
449                 }
450         }
451         modest_ui_actions_on_delete_message (action, win);
452 }
453
454
455
456 void
457 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
458 {
459 #ifdef MODEST_PLATFORM_MAEMO
460         modest_osso_save_state();
461 #endif /* MODEST_PLATFORM_MAEMO */
462
463         g_debug ("closing down, clearing %d item(s) from operation queue",
464                  modest_mail_operation_queue_num_elements
465                  (modest_runtime_get_mail_operation_queue()));
466
467         /* cancel all outstanding operations */
468         modest_mail_operation_queue_cancel_all 
469                 (modest_runtime_get_mail_operation_queue());
470         
471         g_debug ("queue has been cleared");
472
473         /* note: when modest-tny-account-store is finalized,
474            it will automatically set all network connections
475            to offline */
476
477         gtk_main_quit ();
478 }
479
480 void
481 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
482 {
483         gboolean ret_value;
484
485         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
486
487 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
488 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
489 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
490 /*              gboolean ret_value; */
491 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
492 /*      } else if (MODEST_IS_WINDOW (win)) { */
493 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
494 /*      } else { */
495 /*              g_return_if_reached (); */
496 /*      } */
497 }
498
499 void
500 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
501 {
502         GtkClipboard *clipboard = NULL;
503         gchar *selection = NULL;
504
505         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
506         selection = gtk_clipboard_wait_for_text (clipboard);
507
508         /* Question: why is the clipboard being used here? 
509          * It doesn't really make a lot of sense. */
510
511         if (selection)
512         {
513                 modest_address_book_add_address (selection);
514                 g_free (selection);
515         }
516 }
517
518 void
519 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
520 {
521         /* This is currently only implemented for Maemo */
522 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
523         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
524                 run_account_setup_wizard (win);
525                 return;
526         } else  {
527                 /* Show the list of accounts: */
528                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
529                 modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), account_win); 
530         }
531 #else
532         GtkWidget *dialog, *label;
533         
534         /* Create the widgets */
535         
536         dialog = gtk_dialog_new_with_buttons ("Message",
537                                               GTK_WINDOW(win),
538                                               GTK_DIALOG_DESTROY_WITH_PARENT,
539                                               GTK_STOCK_OK,
540                                               GTK_RESPONSE_NONE,
541                                               NULL);
542         label = gtk_label_new ("Hello World!");
543         
544         /* Ensure that the dialog box is destroyed when the user responds. */
545         
546         g_signal_connect_swapped (dialog, "response", 
547                                   G_CALLBACK (gtk_widget_destroy),
548                                   dialog);
549         
550         /* Add the label, and show everything we've added to the dialog. */
551         
552         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
553                            label);
554         gtk_widget_show_all (dialog);
555 #endif /* MODEST_PLATFORM_MAEMO */
556 }
557
558 static void
559 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
560 {
561         ModestWindow *main_window = MODEST_WINDOW (user_data);
562         
563         /* Save any changes. */
564         modest_connection_specific_smtp_window_save_server_accounts (
565                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window), 
566                         modest_window_get_active_account (main_window));
567         gtk_widget_destroy (GTK_WIDGET (window));
568 }
569
570
571
572 void
573 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
574 {
575         /* This is currently only implemented for Maemo,
576          * because it requires an API (libconic) to detect different connection 
577          * possiblities.
578          */
579 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
580         
581         /* Create the window if necessary: */
582         const gchar *active_account_name = modest_window_get_active_account (win);
583         
584         /* TODO: Dim the menu item (not in the UI spec)? or show a warning,
585          * or show the default account?
586          * If we show the default account then the account name should be shown in 
587          * the window when we show it. */
588         if (!active_account_name) {
589                 g_warning ("%s: No account is active.", __FUNCTION__);
590                 return;
591         }
592                 
593         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
594         modest_connection_specific_smtp_window_fill_with_connections (
595                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
596                 modest_runtime_get_account_mgr(), 
597                 active_account_name);
598
599         /* Show the window: */  
600         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
601         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
602         gtk_widget_show (specific_window);
603     
604         /* Save changes when the window is hidden: */
605         g_signal_connect (specific_window, "hide", 
606                 G_CALLBACK (on_smtp_servers_window_hide), win);
607 #endif /* MODEST_PLATFORM_MAEMO */
608 }
609
610 void
611 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
612 {
613         ModestWindow *msg_win = NULL;
614         TnyMsg *msg = NULL;
615         TnyFolder *folder = NULL;
616         gchar *account_name = NULL;
617         gchar *from_str = NULL;
618 /*      GError *err = NULL; */
619         TnyAccount *account = NULL;
620         ModestWindowMgr *mgr;
621         gchar *signature = NULL, *blank_and_signature = NULL;
622
623         /* if there are no accounts yet, just show the wizard */
624         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
625                         run_account_setup_wizard (win);
626                         return;
627         }
628         
629         account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
630         if (!account_name)
631                 account_name = g_strdup (modest_window_get_active_account (win));
632         if (!account_name) {
633                 g_printerr ("modest: no account found\n");
634                 goto cleanup;
635         }
636         
637         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
638                                                                        account_name,
639                                                                        TNY_ACCOUNT_TYPE_STORE);
640         if (!account) {
641                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
642                 goto cleanup;
643         }
644
645         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
646         if (!from_str) {
647                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
648                 goto cleanup;
649         }
650
651         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr (), account_name,
652                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
653                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), account_name,
654                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
655                 blank_and_signature = g_strconcat ("\n", signature, NULL);
656                 g_free (signature);
657         } else {
658                 blank_and_signature = g_strdup ("");
659         }
660
661         msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
662         if (!msg) {
663                 g_printerr ("modest: failed to create new msg\n");
664                 goto cleanup;
665         }
666         
667         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
668         if (!folder) {
669                 g_printerr ("modest: failed to find Drafts folder\n");
670                 goto cleanup;
671         }
672         
673
674         /* Create and register edit window */
675         /* This is destroyed by TOOD. */
676         msg_win = modest_msg_edit_window_new (msg, account_name);
677         mgr = modest_runtime_get_window_mgr ();
678         modest_window_mgr_register_window (mgr, msg_win);
679
680         if (win)
681                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
682                                               GTK_WINDOW (win));        
683         gtk_widget_show_all (GTK_WIDGET (msg_win));
684
685 cleanup:
686         g_free (account_name);
687         g_free (from_str);
688         g_free (blank_and_signature);
689         if (msg_win)
690                 g_object_unref (msg_win);
691         if (account)
692                 g_object_unref (G_OBJECT(account));
693         if (msg)
694                 g_object_unref (G_OBJECT(msg));
695         if (folder)
696                 g_object_unref (G_OBJECT(folder));
697 }
698
699 gboolean 
700 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
701                                        TnyHeader *header,
702                                        TnyMsg *msg)
703 {
704         ModestMailOperationStatus status;
705
706         /* If there is no message or the operation was not successful */
707         status = modest_mail_operation_get_status (mail_op);
708         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
709
710                 /* Remove the header from the preregistered uids */
711                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
712                                                      header);
713
714                 return FALSE;
715         }
716
717         return TRUE;
718 }
719
720 static void
721 open_msg_cb (ModestMailOperation *mail_op, 
722              TnyHeader *header, 
723              TnyMsg *msg, 
724              gpointer user_data)
725 {
726         ModestWindowMgr *mgr = NULL;
727         ModestWindow *parent_win = NULL;
728         ModestWindow *win = NULL;
729         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
730         gchar *account = NULL;
731         TnyFolder *folder;
732         
733         /* Do nothing if there was any problem with the mail
734            operation. The error will be shown by the error_handler of
735            the mail operation */
736         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
737                 return;
738         }
739
740         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
741         folder = tny_header_get_folder (header);
742
743         /* Mark header as read */
744         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
745
746         /* Get account */
747         account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
748         if (!account)
749                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
750         
751         /* Gets folder type (OUTBOX headers will be opened in edit window */
752         if (modest_tny_folder_is_local_folder (folder))
753                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
754
755         /* If the header is in the drafts folder then open the editor,
756            else the message view window */
757         if ((folder_type == TNY_FOLDER_TYPE_DRAFTS) ||
758             (folder_type == TNY_FOLDER_TYPE_OUTBOX)) {
759                 /* we cannot edit without a valid account... */
760                 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
761                         run_account_setup_wizard(parent_win);
762                         goto cleanup;
763                 }
764                 win = modest_msg_edit_window_new (msg, account);
765         } else {
766                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
767                 
768                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
769                         GtkWidget *header_view;
770                         GtkTreeSelection *sel;
771                         GList *sel_list = NULL;
772                         GtkTreeModel *model;
773                         
774                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
775                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
776
777                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
778                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
779
780                         if (sel_list != NULL) {
781                                 GtkTreeRowReference *row_reference;
782
783                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
784                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
785                                 g_list_free (sel_list);
786                                 
787                                 win = modest_msg_view_window_new_with_header_model (msg, 
788                                                                                     account,
789                                                                                     (const gchar*) uid,
790                                                                                     model, 
791                                                                                     row_reference);
792                                 gtk_tree_row_reference_free (row_reference);
793                         } else {
794                                 win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
795                         }
796                 } else {
797                         win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
798                 }
799                 g_free (uid);
800         }
801         
802         /* Register and show new window */
803         if (win != NULL) {
804                 mgr = modest_runtime_get_window_mgr ();
805                 modest_window_mgr_register_window (mgr, win);
806                 g_object_unref (win);
807                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
808                 gtk_widget_show_all (GTK_WIDGET(win));
809         }
810
811         /* Update toolbar dimming state */
812         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
813                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
814         }
815
816 cleanup:
817         /* Free */
818         g_free(account);
819         g_object_unref (parent_win);
820         g_object_unref (folder);
821 }
822
823 void
824 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
825                                                gpointer user_data)
826 {
827         const GError *error;
828         GObject *win = modest_mail_operation_get_source (mail_op);
829
830         error = modest_mail_operation_get_error (mail_op);
831         printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, error->code, error->message);
832  
833         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
834
835                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
836                                                         error->message);
837         } else {
838                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
839                                                         _("mail_ni_ui_folder_get_msg_folder_error"));
840         }
841
842         if (win)
843                 g_object_unref (win);
844 }
845
846 /*
847  * This function is used by both modest_ui_actions_on_open and
848  * modest_ui_actions_on_header_activated. This way we always do the
849  * same when trying to open messages.
850  */
851 static void
852 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
853 {
854         ModestWindowMgr *mgr = NULL;
855         TnyIterator *iter = NULL;
856         ModestMailOperation *mail_op = NULL;
857         TnyList *not_opened_headers = NULL;
858         TnyHeaderFlags flags = 0;
859                 
860         /* Look if we already have a message view for each header. If
861            true, then remove the header from the list of headers to
862            open */
863         mgr = modest_runtime_get_window_mgr ();
864         iter = tny_list_create_iterator (headers);
865         not_opened_headers = tny_simple_list_new ();
866
867         while (!tny_iterator_is_done (iter)) {
868
869                 ModestWindow *window = NULL;
870                 TnyHeader *header = NULL;
871                 gboolean found = FALSE;
872                 
873                 header = TNY_HEADER (tny_iterator_get_current (iter));
874                 if (header)
875                         flags = tny_header_get_flags (header);
876
877                 window = NULL;
878                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
879                 
880                 /* Do not open again the message and present the
881                    window to the user */
882                 if (found) {
883                         if (window)
884                                 gtk_window_present (GTK_WINDOW (window));
885                         else
886                                 /* the header has been registered already, we don't do
887                                  * anything but wait for the window to come up*/
888                                 g_debug ("header %p already registered, waiting for window", header);
889                 } else {
890                         tny_list_append (not_opened_headers, G_OBJECT (header));
891                 }
892
893                 if (header)
894                         g_object_unref (header);
895
896                 tny_iterator_next (iter);
897         }
898         g_object_unref (iter);
899         iter = NULL;
900         
901         /* If some messages would have to be downloaded, ask the user to 
902          * make a connection. It's generally easier to do this here (in the mainloop) 
903          * than later in a thread:
904          */
905         if (tny_list_get_length (not_opened_headers) > 0) {
906                 TnyIterator *iter;
907                 gboolean found = FALSE;
908
909                 iter = tny_list_create_iterator (not_opened_headers);
910                 while (!tny_iterator_is_done (iter) && !found) {
911                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
912                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
913                                 found = TRUE;
914                         else
915                                 tny_iterator_next (iter);
916
917                         g_object_unref (header);
918                 }
919                 g_object_unref (iter);
920
921                 if (found && !modest_platform_connect_and_wait (GTK_WINDOW (win), NULL)) {
922                         g_object_unref (not_opened_headers);
923                         return;                 
924                 }
925         }
926         
927         /* Register the headers before actually creating the windows: */
928         TnyIterator *iter_not_opened = tny_list_create_iterator (not_opened_headers);
929         while (!tny_iterator_is_done (iter_not_opened)) {
930                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
931                 if (header) {
932                         modest_window_mgr_register_header (mgr, header);
933                         g_object_unref (header);
934                 }
935                 
936                 tny_iterator_next (iter_not_opened);
937         }
938         g_object_unref (iter_not_opened);
939         iter_not_opened = NULL;
940         
941         /* Open each message */
942         if (tny_list_get_length (not_opened_headers) > 0) {
943                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
944                                                                          G_OBJECT (win), 
945                                                                          modest_ui_actions_get_msgs_full_error_handler, 
946                                                                          NULL);
947                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
948                 if (tny_list_get_length (not_opened_headers) > 1) {
949                         modest_mail_operation_get_msgs_full (mail_op, 
950                                                              not_opened_headers, 
951                                                              open_msg_cb, 
952                                                              NULL, 
953                                                              NULL);
954                 } else {
955                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
956                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
957                         modest_mail_operation_get_msg (mail_op, header, open_msg_cb, NULL);
958                         g_object_unref (header);
959                         g_object_unref (iter);
960                 }
961                 g_object_unref (mail_op);
962         }
963
964         /* Clean */
965         if (not_opened_headers != NULL)
966                 g_object_unref (not_opened_headers);
967 }
968
969 void
970 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
971 {
972         TnyList *headers;
973
974         /* Get headers */
975         headers = get_selected_headers (win);
976         if (!headers)
977                 return;
978
979         /* Open them */
980         _modest_ui_actions_open (headers, win);
981
982         g_object_unref(headers);
983 }
984
985
986 static void
987 free_reply_forward_helper (gpointer data)
988 {
989         ReplyForwardHelper *helper;
990
991         helper = (ReplyForwardHelper *) data;
992         g_free (helper->account_name);
993         g_slice_free (ReplyForwardHelper, helper);
994 }
995
996 static void
997 reply_forward_cb (ModestMailOperation *mail_op, 
998                   TnyHeader *header, 
999                   TnyMsg *msg,
1000                   gpointer user_data)
1001 {
1002         TnyMsg *new_msg;
1003         ReplyForwardHelper *rf_helper;
1004         ModestWindow *msg_win = NULL;
1005         ModestEditType edit_type;
1006         gchar *from = NULL;
1007         TnyAccount *account = NULL;
1008         ModestWindowMgr *mgr = NULL;
1009         gchar *signature = NULL;
1010
1011         /* If there was any error. The mail operation could be NULL,
1012            this means that we already have the message downloaded and
1013            that we didn't do a mail operation to retrieve it */
1014         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1015                 return;
1016                         
1017         g_return_if_fail (user_data != NULL);
1018         rf_helper = (ReplyForwardHelper *) user_data;
1019
1020         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1021                                                    rf_helper->account_name);
1022         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
1023                                          rf_helper->account_name,
1024                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
1025                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
1026                                                            rf_helper->account_name,
1027                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
1028         }
1029
1030         /* Create reply mail */
1031         switch (rf_helper->action) {
1032         case ACTION_REPLY:
1033                 new_msg = 
1034                         modest_tny_msg_create_reply_msg (msg,  from, signature,
1035                                                          rf_helper->reply_forward_type,
1036                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1037                 break;
1038         case ACTION_REPLY_TO_ALL:
1039                 new_msg = 
1040                         modest_tny_msg_create_reply_msg (msg, from, signature, rf_helper->reply_forward_type,
1041                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1042                 edit_type = MODEST_EDIT_TYPE_REPLY;
1043                 break;
1044         case ACTION_FORWARD:
1045                 new_msg = 
1046                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1047                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1048                 break;
1049         default:
1050                 g_return_if_reached ();
1051                 return;
1052         }
1053
1054         g_free (signature);
1055
1056         if (!new_msg) {
1057                 g_printerr ("modest: failed to create message\n");
1058                 goto cleanup;
1059         }
1060
1061         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1062                                                                        rf_helper->account_name,
1063                                                                        TNY_ACCOUNT_TYPE_STORE);
1064         if (!account) {
1065                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1066                 goto cleanup;
1067         }
1068
1069         /* Create and register the windows */
1070         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
1071         mgr = modest_runtime_get_window_mgr ();
1072         modest_window_mgr_register_window (mgr, msg_win);
1073
1074         if (rf_helper->parent_window != NULL) {
1075                 gdouble parent_zoom;
1076
1077                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1078                 modest_window_set_zoom (msg_win, parent_zoom);
1079         }
1080
1081         /* Show edit window */
1082         gtk_widget_show_all (GTK_WIDGET (msg_win));
1083
1084 cleanup:
1085         if (msg_win)
1086                 g_object_unref (msg_win);
1087         if (new_msg)
1088                 g_object_unref (G_OBJECT (new_msg));
1089         if (account)
1090                 g_object_unref (G_OBJECT (account));
1091 /*      g_object_unref (msg); */
1092         g_object_unref (header);
1093         free_reply_forward_helper (rf_helper);
1094 }
1095
1096 /*
1097  * Checks a list of headers. If any of them are not currently
1098  * downloaded (CACHED) then it asks the user for permission to
1099  * download them.
1100  *
1101  * Returns FALSE if the user does not want to download the
1102  * messages. Returns TRUE if the user allowed the download or if all
1103  * of them are currently downloaded
1104  */
1105 static gboolean
1106 download_uncached_messages (TnyList *header_list, 
1107                             GtkWindow *win,
1108                             gboolean reply_fwd)
1109 {
1110         TnyIterator *iter;
1111         gboolean retval;
1112         gint uncached_messages = 0;
1113
1114         iter = tny_list_create_iterator (header_list);
1115         while (!tny_iterator_is_done (iter)) {
1116                 TnyHeader *header;
1117
1118                 header = TNY_HEADER (tny_iterator_get_current (iter));
1119                 if (header) {
1120                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1121                                 uncached_messages ++;
1122                         g_object_unref (header);
1123                 }
1124
1125                 tny_iterator_next (iter);
1126         }
1127         g_object_unref (iter);
1128
1129         /* Ask for user permission to download the messages */
1130         retval = TRUE;
1131         if (uncached_messages > 0) {
1132                 GtkResponseType response;
1133                 if (reply_fwd)
1134                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1135                                                                             _("emev_nc_include_original"));
1136                 else
1137                         response =
1138                                 modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1139                                                                          ngettext("mcen_nc_get_msg",
1140                                                                                   "mcen_nc_get_msgs",
1141                                                                                   uncached_messages));
1142                 if (response == GTK_RESPONSE_CANCEL)
1143                         retval = FALSE;
1144                 else {
1145                         /* If a download will be necessary, make sure that we have a connection: */
1146                         retval = modest_platform_connect_and_wait(win, NULL);   
1147                 }
1148         }
1149         return retval;
1150 }
1151
1152
1153 /*
1154  * Common code for the reply and forward actions
1155  */
1156 static void
1157 reply_forward (ReplyForwardAction action, ModestWindow *win)
1158 {
1159         ModestMailOperation *mail_op = NULL;
1160         TnyList *header_list = NULL;
1161         ReplyForwardHelper *rf_helper = NULL;
1162         guint reply_forward_type;
1163         gboolean continue_download;
1164         
1165         g_return_if_fail (MODEST_IS_WINDOW(win));
1166
1167         /* we need an account when editing */
1168         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1169                 run_account_setup_wizard (win);
1170                 return;
1171         }
1172         
1173         header_list = get_selected_headers (win);
1174         if (!header_list)
1175                 return;
1176
1177         /* Check that the messages have been previously downloaded */
1178         continue_download = download_uncached_messages (header_list, GTK_WINDOW (win), TRUE);
1179         if (!continue_download) {
1180                 g_object_unref (header_list);
1181                 return;
1182         }
1183         
1184         reply_forward_type = 
1185                 modest_conf_get_int (modest_runtime_get_conf (),
1186                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1187                                      NULL);
1188         /* We assume that we can only select messages of the
1189            same folder and that we reply all of them from the
1190            same account. In fact the interface currently only
1191            allows single selection */
1192         
1193         /* Fill helpers */
1194         rf_helper = g_slice_new0 (ReplyForwardHelper);
1195         rf_helper->reply_forward_type = reply_forward_type;
1196         rf_helper->action = action;
1197         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1198         
1199         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1200                 rf_helper->parent_window = GTK_WIDGET (win);
1201         if (!rf_helper->account_name)
1202                 rf_helper->account_name =
1203                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1204
1205         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1206                 TnyMsg *msg;
1207                 TnyHeader *header;
1208                 /* Get header and message. Do not free them here, the
1209                    reply_forward_cb must do it */
1210                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1211                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1212                 if (!msg || !header) {
1213                         if (msg)
1214                                 g_object_unref (msg);
1215                         if (header)
1216                                 g_object_unref (header);
1217                         g_printerr ("modest: no message found\n");
1218                         return;
1219                 } else {
1220                         reply_forward_cb (NULL, header, msg, rf_helper);
1221                 }
1222         } else {
1223                 TnyHeader *header;
1224                 TnyIterator *iter;
1225
1226                 /* Retrieve messages */
1227                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1228                                                                          G_OBJECT(win),
1229                                                                          modest_ui_actions_get_msgs_full_error_handler, 
1230                                                                          NULL);
1231                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1232
1233                 /* Only reply/forward to one message */
1234                 iter = tny_list_create_iterator (header_list);
1235                 header = TNY_HEADER (tny_iterator_get_current (iter));
1236                 g_object_unref (iter);
1237
1238                 if (header) {
1239                         modest_mail_operation_get_msg (mail_op,
1240                                                header,
1241                                                reply_forward_cb,
1242                                                rf_helper);
1243
1244 /*                      modest_mail_operation_get_msgs_full (mail_op,  */
1245 /*                                                   header_list,  */
1246 /*                                                   reply_forward_cb,  */
1247 /*                                                   rf_helper,  */
1248 /*                                                   free_reply_forward_helper); */
1249
1250                         g_object_unref (header);
1251                 }
1252
1253                 /* Clean */
1254                 g_object_unref(mail_op);
1255         }
1256
1257         /* Free */
1258         g_object_unref (header_list);
1259 }
1260
1261 void
1262 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1263 {
1264         g_return_if_fail (MODEST_IS_WINDOW(win));
1265
1266         reply_forward (ACTION_REPLY, win);
1267 }
1268
1269 void
1270 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1271 {
1272         g_return_if_fail (MODEST_IS_WINDOW(win));
1273
1274         reply_forward (ACTION_FORWARD, win);
1275 }
1276
1277 void
1278 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1279 {
1280         g_return_if_fail (MODEST_IS_WINDOW(win));
1281
1282         reply_forward (ACTION_REPLY_TO_ALL, win);
1283 }
1284
1285 void 
1286 modest_ui_actions_on_next (GtkAction *action, 
1287                            ModestWindow *window)
1288 {
1289         if (MODEST_IS_MAIN_WINDOW (window)) {
1290                 GtkWidget *header_view;
1291
1292                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1293                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1294                 if (!header_view)
1295                         return;
1296         
1297                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
1298         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1299                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
1300         } else {
1301                 g_return_if_reached ();
1302         }
1303 }
1304
1305 void 
1306 modest_ui_actions_on_prev (GtkAction *action, 
1307                            ModestWindow *window)
1308 {
1309         g_return_if_fail (MODEST_IS_WINDOW(window));
1310
1311         if (MODEST_IS_MAIN_WINDOW (window)) {
1312                 GtkWidget *header_view;
1313                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1314                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1315                 if (!header_view)
1316                         return;
1317                 
1318                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1319         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1320                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1321         } else {
1322                 g_return_if_reached ();
1323         }
1324 }
1325
1326 void 
1327 modest_ui_actions_on_sort (GtkAction *action, 
1328                            ModestWindow *window)
1329 {
1330         g_return_if_fail (MODEST_IS_WINDOW(window));
1331
1332         if (MODEST_IS_MAIN_WINDOW (window)) {
1333                 GtkWidget *header_view;
1334                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1335                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1336                 if (!header_view) {
1337                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1338
1339                         return;
1340                 }
1341
1342                 /* Show sorting dialog */
1343                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1344         }
1345 }
1346
1347 static void
1348 new_messages_arrived (ModestMailOperation *self, 
1349                       gint new_messages,
1350                       gpointer user_data)
1351 {
1352         if (new_messages == 0)
1353                 return;
1354
1355         modest_platform_on_new_msg ();
1356 }
1357
1358 /*
1359  * This function performs the send & receive required actions. The
1360  * window is used to create the mail operation. Typically it should
1361  * always be the main window, but we pass it as argument in order to
1362  * be more flexible.
1363  */
1364 void
1365 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1366 {
1367         gchar *acc_name = NULL;
1368         ModestMailOperation *mail_op;
1369
1370         /* If no account name was provided then get the current account, and if
1371            there is no current account then pick the default one: */
1372         if (!account_name) {
1373                 acc_name = g_strdup (modest_window_get_active_account(win));
1374                 if (!acc_name)
1375                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1376                 if (!acc_name) {
1377                         g_printerr ("modest: cannot get default account\n");
1378                         return;
1379                 }
1380         } else {
1381                 acc_name = g_strdup (account_name);
1382         }
1383
1384         /* Set send/receive operation in progress */    
1385         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1386
1387         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1388                                                                  G_OBJECT (win),
1389                                                                  modest_ui_actions_send_receive_error_handler,
1390                                                                  NULL);
1391
1392         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1393                           G_CALLBACK (_on_send_receive_progress_changed), 
1394                           win);
1395
1396         /* Send & receive. */
1397         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1398         /* Receive and then send. The operation is tagged initially as
1399            a receive operation because the account update performs a
1400            receive and then a send. The operation changes its type
1401            internally, so the progress objects will receive the proper
1402            progress information */
1403         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1404         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, NULL);
1405         g_object_unref (G_OBJECT (mail_op));
1406         
1407         /* Free */
1408         g_free (acc_name);
1409 }
1410
1411
1412 static void
1413 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1414                                   ModestWindow *win)
1415 {
1416         TnyTransportAccount *transport_account;
1417         TnySendQueue *send_queue = NULL;
1418         GError *error = NULL;
1419
1420         /* Get transport account */
1421         transport_account =
1422                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1423                                       (modest_runtime_get_account_store(),
1424                                        account_name,
1425                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1426         if (!transport_account) {
1427                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1428                 goto frees;
1429         }
1430
1431         /* Get send queue*/
1432         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1433         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1434                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1435                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1436                              "modest: could not find send queue for account\n");
1437         } else {
1438                 /* Keeep messages in outbox folder */
1439                 tny_send_queue_cancel (send_queue, FALSE, &error);
1440         }       
1441
1442  frees:
1443         if (transport_account != NULL) 
1444                 g_object_unref (G_OBJECT (transport_account));
1445 }
1446
1447 static void
1448 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1449 {
1450         GSList *account_names, *iter;
1451
1452         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1453                                                           TRUE);
1454
1455         iter = account_names;
1456         while (iter) {                  
1457                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1458                 iter = g_slist_next (iter);
1459         }
1460
1461         modest_account_mgr_free_account_names (account_names);
1462         account_names = NULL;
1463 }
1464
1465 void
1466 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1467
1468 {
1469         /* Check if accounts exist */
1470         gboolean accounts_exist = 
1471                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1472         
1473         /* If not, allow the user to create an account before trying to send/receive. */
1474         if (!accounts_exist)
1475                 modest_ui_actions_on_accounts (NULL, win);
1476         
1477         /* Cancel all sending operaitons */     
1478         modest_ui_actions_cancel_send_all (win);
1479 }
1480
1481 /*
1482  * Refreshes all accounts. This function will be used by automatic
1483  * updates
1484  */
1485 void
1486 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1487 {
1488         GSList *account_names, *iter;
1489
1490         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1491                                                           TRUE);
1492
1493         iter = account_names;
1494         while (iter) {                  
1495                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1496                 iter = g_slist_next (iter);
1497         }
1498
1499         modest_account_mgr_free_account_names (account_names);
1500         account_names = NULL;
1501 }
1502
1503 void 
1504 modest_do_refresh_current_folder(ModestWindow *win)
1505 {
1506         /* Refresh currently selected folder. Note that if we only
1507            want to retreive the headers, then the refresh only will
1508            invoke a poke_status over all folders, i.e., only the
1509            total/unread count will be updated */
1510         if (MODEST_IS_MAIN_WINDOW (win)) {
1511                 GtkWidget *header_view, *folder_view;
1512                 TnyFolderStore *folder_store;
1513
1514                 /* Get folder and header view */
1515                 folder_view = 
1516                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1517                                                              MODEST_WIDGET_TYPE_FOLDER_VIEW);
1518
1519                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1520
1521                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1522                         header_view = 
1523                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1524                                                                      MODEST_WIDGET_TYPE_HEADER_VIEW);
1525                 
1526                         /* We do not need to set the contents style
1527                            because it hasn't changed. We also do not
1528                            need to save the widget status. Just force
1529                            a refresh */
1530                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1531                                                        TNY_FOLDER (folder_store),
1532                                                        folder_refreshed_cb,
1533                                                        MODEST_MAIN_WINDOW (win));
1534                 }
1535                 
1536                 if (folder_store)
1537                         g_object_unref (folder_store);
1538         }
1539 }
1540
1541
1542 /*
1543  * Handler of the click on Send&Receive button in the main toolbar
1544  */
1545 void
1546 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1547 {
1548         /* Check if accounts exist */
1549         gboolean accounts_exist = 
1550                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1551         
1552         /* If not, allow the user to create an account before trying to send/receive. */
1553         if (!accounts_exist)
1554                 modest_ui_actions_on_accounts (NULL, win);
1555
1556         modest_do_refresh_current_folder (win);
1557         
1558         /* Refresh the active account */
1559         modest_ui_actions_do_send_receive (NULL, win);
1560 }
1561
1562
1563 void
1564 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1565 {
1566         ModestConf *conf;
1567         GtkWidget *header_view;
1568         
1569         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1570
1571         header_view = modest_main_window_get_child_widget (main_window,
1572                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1573         if (!header_view)
1574                 return;
1575
1576         conf = modest_runtime_get_conf ();
1577         
1578         /* what is saved/restored is depending on the style; thus; we save with
1579          * old style, then update the style, and restore for this new style
1580          */
1581         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1582         
1583         if (modest_header_view_get_style
1584             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1585                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1586                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1587         else
1588                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1589                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1590
1591         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1592                                       MODEST_CONF_HEADER_VIEW_KEY);
1593 }
1594
1595
1596 void 
1597 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1598                                       TnyHeader *header,
1599                                       ModestMainWindow *main_window)
1600 {
1601         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1602         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1603         
1604         /* If no header has been selected then exit */
1605         if (!header)
1606                 return;
1607
1608         /* Update focus */
1609         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1610             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1611
1612         /* Update Main window title */
1613         if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
1614                 const gchar *subject = tny_header_get_subject (header);
1615                 if (subject && strlen(subject) > 0)
1616                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
1617                 else
1618                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
1619         }
1620
1621         /* Update toolbar dimming state */
1622         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1623 }
1624
1625 void
1626 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1627                                        TnyHeader *header,
1628                                        ModestMainWindow *main_window)
1629 {
1630         TnyList *headers;
1631
1632         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1633         
1634         if (!header)
1635                 return;
1636
1637         headers = tny_simple_list_new ();
1638         tny_list_prepend (headers, G_OBJECT (header));
1639
1640         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1641
1642         g_object_unref (headers);
1643 }
1644
1645 static void
1646 set_active_account_from_tny_account (TnyAccount *account,
1647                                      ModestWindow *window)
1648 {
1649         const gchar *server_acc_name = tny_account_get_id (account);
1650         
1651         /* We need the TnyAccount provided by the
1652            account store because that is the one that
1653            knows the name of the Modest account */
1654         TnyAccount *modest_server_account = modest_server_account = 
1655                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1656                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1657                                                              server_acc_name);
1658         
1659         const gchar *modest_acc_name = 
1660                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1661         modest_window_set_active_account (window, modest_acc_name);
1662         g_object_unref (modest_server_account);
1663 }
1664
1665
1666 static void
1667 folder_refreshed_cb (ModestMailOperation *mail_op, 
1668                      TnyFolder *folder, 
1669                      gpointer user_data)
1670 {
1671         ModestMainWindow *win = NULL;
1672         GtkWidget *header_view;
1673         TnyFolder *current_folder;
1674
1675         g_return_if_fail (TNY_IS_FOLDER (folder));
1676
1677         win = MODEST_MAIN_WINDOW (user_data);
1678         header_view = 
1679                 modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
1680
1681         if (header_view) {
1682                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
1683                 if (current_folder != NULL && folder != current_folder) {
1684                         return;
1685                 }
1686         }
1687
1688         /* Check if folder is empty and set headers view contents style */
1689         if (tny_folder_get_all_count (folder) == 0) {
1690         printf ("DEBUG: %s: tny_folder_get_all_count() returned 0.\n", __FUNCTION__);
1691                 modest_main_window_set_contents_style (win,
1692                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1693         } else {
1694                 printf ("DEBUG: %s: tny_folder_get_all_count() returned >0.\n", __FUNCTION__);
1695         }
1696 }
1697
1698 void 
1699 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1700                                                TnyFolderStore *folder_store, 
1701                                                gboolean selected,
1702                                                ModestMainWindow *main_window)
1703 {
1704         ModestConf *conf;
1705         GtkWidget *header_view;
1706
1707         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1708
1709         header_view = modest_main_window_get_child_widget(main_window,
1710                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1711         if (!header_view)
1712                 return;
1713         
1714         conf = modest_runtime_get_conf ();
1715
1716         if (TNY_IS_ACCOUNT (folder_store)) {
1717                 if (selected) {
1718                         /* Update active account */
1719                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1720                         /* Show account details */
1721                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1722                 }
1723         } else {
1724                 if (TNY_IS_FOLDER (folder_store) && selected) {
1725                         
1726                         /* Update the active account */
1727                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1728                         if (account) {
1729                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1730                                 g_object_unref (account);
1731                                 account = NULL;
1732                         }
1733
1734                         /* Set the header style by default, it could
1735                            be changed later by the refresh callback to
1736                            empty */
1737                         modest_main_window_set_contents_style (main_window, 
1738                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1739
1740                         /* Set folder on header view. This function
1741                            will call tny_folder_refresh_async so we
1742                            pass a callback that will be called when
1743                            finished. We use that callback to set the
1744                            empty view if there are no messages */
1745                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1746                                                        TNY_FOLDER (folder_store),
1747                                                        folder_refreshed_cb,
1748                                                        main_window);
1749                         
1750                         /* Restore configuration. We need to do this
1751                            *after* the set_folder because the widget
1752                            memory asks the header view about its
1753                            folder  */
1754                         modest_widget_memory_restore (modest_runtime_get_conf (), 
1755                                                       G_OBJECT(header_view),
1756                                                       MODEST_CONF_HEADER_VIEW_KEY);
1757                 } else {
1758                         /* Update the active account */
1759                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1760                         /* Save only if we're seeing headers */
1761                         if (modest_main_window_get_contents_style (main_window) ==
1762                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1763                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
1764                                                            MODEST_CONF_HEADER_VIEW_KEY);
1765                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
1766                 }
1767         }
1768
1769         /* Update toolbar dimming state */
1770         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1771 }
1772
1773 void 
1774 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1775                                      ModestWindow *win)
1776 {
1777         GtkWidget *dialog;
1778         gchar *txt, *item;
1779         gboolean online;
1780
1781         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1782         
1783         online = tny_device_is_online (modest_runtime_get_device());
1784
1785         if (online) {
1786                 /* already online -- the item is simply not there... */
1787                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1788                                                  GTK_DIALOG_MODAL,
1789                                                  GTK_MESSAGE_WARNING,
1790                                                  GTK_BUTTONS_OK,
1791                                                  _("The %s you selected cannot be found"),
1792                                                  item);
1793                 gtk_dialog_run (GTK_DIALOG(dialog));
1794         } else {
1795                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1796                                                       GTK_WINDOW (win),
1797                                                       GTK_DIALOG_MODAL,
1798                                                       GTK_STOCK_CANCEL,
1799                                                       GTK_RESPONSE_REJECT,
1800                                                       GTK_STOCK_OK,
1801                                                       GTK_RESPONSE_ACCEPT,
1802                                                       NULL);
1803                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1804                                          "Do you want to get online?"), item);
1805                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1806                                     gtk_label_new (txt), FALSE, FALSE, 0);
1807                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1808                 g_free (txt);
1809
1810                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1811                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1812                         /* TODO: Comment about why is this commented out: */
1813                         /* modest_platform_connect_and_wait (); */
1814                 }
1815         }
1816         gtk_widget_destroy (dialog);
1817 }
1818
1819 void
1820 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1821                                      ModestWindow *win)
1822 {
1823         /* g_message ("%s %s", __FUNCTION__, link); */
1824 }       
1825
1826
1827 void
1828 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1829                                         ModestWindow *win)
1830 {
1831         modest_platform_activate_uri (link);
1832 }
1833
1834 void
1835 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1836                                           ModestWindow *win)
1837 {
1838         modest_platform_show_uri_popup (link);
1839 }
1840
1841 void
1842 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1843                                              ModestWindow *win)
1844 {
1845         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1846 }
1847
1848 void
1849 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1850                                           const gchar *address,
1851                                           ModestWindow *win)
1852 {
1853         /* g_message ("%s %s", __FUNCTION__, address); */
1854 }
1855
1856 void
1857 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1858 {
1859         TnyTransportAccount *transport_account;
1860         ModestMailOperation *mail_operation;
1861         MsgData *data;
1862         gchar *account_name, *from;
1863         ModestAccountMgr *account_mgr;
1864         gchar *info_text = NULL;
1865
1866         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1867         
1868         data = modest_msg_edit_window_get_msg_data (edit_window);
1869
1870         account_mgr = modest_runtime_get_account_mgr();
1871         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1872         if (!account_name) 
1873                 account_name = modest_account_mgr_get_default_account (account_mgr);
1874         if (!account_name) {
1875                 g_printerr ("modest: no account found\n");
1876                 modest_msg_edit_window_free_msg_data (edit_window, data);
1877                 return;
1878         }
1879
1880         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1881                 account_name = g_strdup (data->account_name);
1882         }
1883
1884         transport_account =
1885                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1886                                       (modest_runtime_get_account_store(),
1887                                        account_name,
1888                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1889         if (!transport_account) {
1890                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1891                 g_free (account_name);
1892                 modest_msg_edit_window_free_msg_data (edit_window, data);
1893                 return;
1894         }
1895         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1896
1897         /* Create the mail operation */         
1898         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1899         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1900
1901         modest_mail_operation_save_to_drafts (mail_operation,
1902                                               transport_account,
1903                                               data->draft_msg,
1904                                               edit_window,
1905                                               from,
1906                                               data->to, 
1907                                               data->cc, 
1908                                               data->bcc,
1909                                               data->subject, 
1910                                               data->plain_body, 
1911                                               data->html_body,
1912                                               data->attachments,
1913                                               data->priority_flags);
1914         /* Frees */
1915         g_free (from);
1916         g_free (account_name);
1917         g_object_unref (G_OBJECT (transport_account));
1918         g_object_unref (G_OBJECT (mail_operation));
1919
1920         modest_msg_edit_window_free_msg_data (edit_window, data);
1921
1922         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
1923         modest_platform_information_banner (NULL, NULL, info_text);
1924         g_free (info_text);
1925 }
1926
1927 /* For instance, when clicking the Send toolbar button when editing a message: */
1928 void
1929 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1930 {
1931         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1932
1933         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
1934                 return;
1935         
1936         /* Offer the connection dialog, if necessary: */        
1937         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window), NULL))
1938                 return;
1939         
1940         /* FIXME: Code added just for testing. The final version will
1941            use the send queue provided by tinymail and some
1942            classifier */
1943         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
1944         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1945         if (!account_name) 
1946                 account_name = modest_account_mgr_get_default_account (account_mgr);
1947                 
1948         if (!account_name) {
1949                 g_printerr ("modest: no account found\n");
1950                 return;
1951         }
1952         
1953         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
1954
1955         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1956                 account_name = g_strdup (data->account_name);
1957         }
1958         
1959         /* Get the currently-active transport account for this modest account: */
1960         TnyTransportAccount *transport_account =
1961                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1962                                       (modest_runtime_get_account_store(),
1963                                        account_name));
1964         if (!transport_account) {
1965                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1966                 g_free (account_name);
1967                 modest_msg_edit_window_free_msg_data (edit_window, data);
1968                 return;
1969         }
1970         
1971         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
1972
1973         /* mail content checks and dialogs */
1974         if (data->subject == NULL || data->subject[0] == '\0') {
1975                 GtkResponseType response;
1976                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1977                                                                     _("mcen_nc_subject_is_empty_send"));
1978                 if (response == GTK_RESPONSE_CANCEL) {
1979                         g_free (account_name);
1980                         return;
1981                 }
1982         }
1983
1984         if (data->plain_body == NULL || data->plain_body[0] == '\0') {
1985                 GtkResponseType response;
1986                 gchar *note_message;
1987                 gchar *note_subject = data->subject;
1988                 if (note_subject == NULL || note_subject[0] == '\0')
1989                         note_subject = _("mail_va_no_subject");
1990                 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
1991                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1992                                                                     note_message);
1993                 g_free (note_message);
1994                 if (response == GTK_RESPONSE_CANCEL) {
1995                         g_free (account_name);
1996                         return;
1997                 }
1998         }
1999
2000         modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2001
2002         /* Create the mail operation */
2003         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
2004         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2005
2006         modest_mail_operation_send_new_mail (mail_operation,
2007                                              transport_account,
2008                                              data->draft_msg,
2009                                              from,
2010                                              data->to, 
2011                                              data->cc, 
2012                                              data->bcc,
2013                                              data->subject, 
2014                                              data->plain_body, 
2015                                              data->html_body,
2016                                              data->attachments,
2017                                              data->priority_flags);
2018                                              
2019         /* Free data: */
2020         g_free (from);
2021         g_free (account_name);
2022         g_object_unref (G_OBJECT (transport_account));
2023         g_object_unref (G_OBJECT (mail_operation));
2024
2025         modest_msg_edit_window_free_msg_data (edit_window, data);
2026         modest_msg_edit_window_set_sent (edit_window, TRUE);
2027
2028         /* Save settings and close the window: */
2029         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2030 }
2031
2032 void 
2033 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2034                                   ModestMsgEditWindow *window)
2035 {
2036         ModestMsgEditFormatState *format_state = NULL;
2037
2038         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2039         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2040
2041         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2042                 return;
2043
2044         format_state = modest_msg_edit_window_get_format_state (window);
2045         g_return_if_fail (format_state != NULL);
2046
2047         format_state->bold = gtk_toggle_action_get_active (action);
2048         modest_msg_edit_window_set_format_state (window, format_state);
2049         g_free (format_state);
2050         
2051 }
2052
2053 void 
2054 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2055                                      ModestMsgEditWindow *window)
2056 {
2057         ModestMsgEditFormatState *format_state = NULL;
2058
2059         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2060         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2061
2062         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2063                 return;
2064
2065         format_state = modest_msg_edit_window_get_format_state (window);
2066         g_return_if_fail (format_state != NULL);
2067
2068         format_state->italics = gtk_toggle_action_get_active (action);
2069         modest_msg_edit_window_set_format_state (window, format_state);
2070         g_free (format_state);
2071         
2072 }
2073
2074 void 
2075 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2076                                      ModestMsgEditWindow *window)
2077 {
2078         ModestMsgEditFormatState *format_state = NULL;
2079
2080         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2081         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2082
2083         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2084                 return;
2085
2086         format_state = modest_msg_edit_window_get_format_state (window);
2087         g_return_if_fail (format_state != NULL);
2088
2089         format_state->bullet = gtk_toggle_action_get_active (action);
2090         modest_msg_edit_window_set_format_state (window, format_state);
2091         g_free (format_state);
2092         
2093 }
2094
2095 void 
2096 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2097                                      GtkRadioAction *selected,
2098                                      ModestMsgEditWindow *window)
2099 {
2100         ModestMsgEditFormatState *format_state = NULL;
2101         GtkJustification value;
2102
2103         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2104
2105         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2106                 return;
2107
2108         value = gtk_radio_action_get_current_value (selected);
2109
2110         format_state = modest_msg_edit_window_get_format_state (window);
2111         g_return_if_fail (format_state != NULL);
2112
2113         format_state->justification = value;
2114         modest_msg_edit_window_set_format_state (window, format_state);
2115         g_free (format_state);
2116 }
2117
2118 void 
2119 modest_ui_actions_on_select_editor_color (GtkAction *action,
2120                                           ModestMsgEditWindow *window)
2121 {
2122         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2123         g_return_if_fail (GTK_IS_ACTION (action));
2124
2125         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2126                 return;
2127
2128         modest_msg_edit_window_select_color (window);
2129 }
2130
2131 void 
2132 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2133                                                      ModestMsgEditWindow *window)
2134 {
2135         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2136         g_return_if_fail (GTK_IS_ACTION (action));
2137
2138         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2139                 return;
2140
2141         modest_msg_edit_window_select_background_color (window);
2142 }
2143
2144 void 
2145 modest_ui_actions_on_insert_image (GtkAction *action,
2146                                    ModestMsgEditWindow *window)
2147 {
2148         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2149         g_return_if_fail (GTK_IS_ACTION (action));
2150
2151         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2152                 return;
2153
2154         modest_msg_edit_window_insert_image (window);
2155 }
2156
2157 void 
2158 modest_ui_actions_on_attach_file (GtkAction *action,
2159                                   ModestMsgEditWindow *window)
2160 {
2161         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2162         g_return_if_fail (GTK_IS_ACTION (action));
2163
2164         modest_msg_edit_window_offer_attach_file (window);
2165 }
2166
2167 void 
2168 modest_ui_actions_on_remove_attachments (GtkAction *action,
2169                                          ModestMsgEditWindow *window)
2170 {
2171         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2172         g_return_if_fail (GTK_IS_ACTION (action));
2173
2174         modest_msg_edit_window_remove_attachments (window, NULL);
2175 }
2176
2177 static void
2178 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2179                                             gpointer user_data)
2180 {
2181         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2182         const GError *error = modest_mail_operation_get_error (mail_op);
2183
2184         if(error)
2185         {
2186                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2187                                                     modest_mail_operation_get_error (mail_op)->message);
2188         }
2189 }
2190
2191 static void
2192 modest_ui_actions_create_folder(GtkWidget *parent_window,
2193                                 GtkWidget *folder_view)
2194 {
2195         TnyFolderStore *parent_folder;
2196
2197         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2198         
2199         if (parent_folder) {
2200                 gboolean finished = FALSE;
2201                 gint result;
2202                 gchar *folder_name = NULL, *suggested_name = NULL;
2203
2204                 /* Run the new folder dialog */
2205                 while (!finished) {
2206                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2207                                                                         parent_folder,
2208                                                                         suggested_name,
2209                                                                         &folder_name);
2210
2211                         g_free (suggested_name);
2212                         suggested_name = NULL;
2213
2214                         if (result == GTK_RESPONSE_REJECT) {
2215                                 finished = TRUE;
2216                         } else {
2217                                 ModestMailOperation *mail_op;
2218                                 TnyFolder *new_folder = NULL;
2219
2220                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2221                                                                                           G_OBJECT(parent_window),
2222                                                                                           modest_ui_actions_new_folder_error_handler,
2223                                                                                           parent_window);
2224
2225                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2226                                                                  mail_op);
2227                                 new_folder = modest_mail_operation_create_folder (mail_op,
2228                                                                                   parent_folder,
2229                                                                                   (const gchar *) folder_name);
2230                                 if (new_folder) {
2231                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2232                                                                           new_folder, TRUE);
2233
2234                                         g_object_unref (new_folder);
2235                                         finished = TRUE;
2236                                 }
2237                                 g_object_unref (mail_op);
2238                         }
2239
2240                         suggested_name = folder_name;
2241                         folder_name = NULL;
2242                 }
2243
2244                 g_object_unref (parent_folder);
2245         }
2246 }
2247
2248 void 
2249 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2250 {
2251         GtkWidget *folder_view;
2252         
2253         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2254
2255         folder_view = modest_main_window_get_child_widget (main_window,
2256                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2257         if (!folder_view)
2258                 return;
2259
2260         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2261 }
2262
2263 static void
2264 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2265                                                gpointer user_data)
2266 {
2267         GObject *win = modest_mail_operation_get_source (mail_op);
2268         const GError *error = NULL;
2269         const gchar *message = NULL;
2270         
2271         /* Get error message */
2272         error = modest_mail_operation_get_error (mail_op);
2273         if (error != NULL && error->message != NULL) {
2274                 message = error->message;
2275         } else {
2276                 message = _("!!! FIXME: Unable to rename");
2277         }
2278         
2279         /* Show notification dialog */
2280         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
2281         g_object_unref (win);
2282 }
2283
2284 void 
2285 modest_ui_actions_on_rename_folder (GtkAction *action,
2286                                      ModestMainWindow *main_window)
2287 {
2288         TnyFolderStore *folder;
2289         GtkWidget *folder_view;
2290         GtkWidget *header_view; 
2291
2292         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2293
2294         folder_view = modest_main_window_get_child_widget (main_window,
2295                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2296         if (!folder_view)
2297                 return;
2298
2299         header_view = modest_main_window_get_child_widget (main_window,
2300                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2301         
2302         if (!header_view)
2303                 return;
2304
2305         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2306         if (!folder)
2307                 return;
2308
2309         /* Offer the connection dialog if necessary: */
2310         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2311                 g_object_unref (G_OBJECT (folder));
2312                 return;
2313         }
2314
2315         
2316         if (TNY_IS_FOLDER (folder)) {
2317                 gchar *folder_name;
2318                 gint response;
2319                 const gchar *current_name;
2320
2321                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2322                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), NULL,
2323                                                                      current_name, &folder_name);
2324
2325                 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2326                         ModestMailOperation *mail_op;
2327
2328                         mail_op = 
2329                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO, 
2330                                                                                G_OBJECT(main_window),
2331                                                                                modest_ui_actions_rename_folder_error_handler,
2332                                                                                NULL);
2333
2334
2335                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2336                                                          mail_op);
2337
2338                         modest_header_view_clear (MODEST_HEADER_VIEW (header_view));
2339                         
2340                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2341                                                           TNY_FOLDER(folder), TRUE);
2342
2343
2344                         modest_header_view_clear ((ModestHeaderView *) header_view);
2345  
2346                         modest_mail_operation_rename_folder (mail_op,
2347                                                              TNY_FOLDER (folder),
2348                                                              (const gchar *) folder_name);
2349
2350                         g_object_unref (mail_op);
2351                         g_free (folder_name);
2352                 }
2353         }
2354         g_object_unref (folder);
2355 }
2356
2357 static void
2358 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2359                                                gpointer user_data)
2360 {
2361         GObject *win = modest_mail_operation_get_source (mail_op);
2362
2363         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2364                                                 _("mail_in_ui_folder_delete_error"));
2365         g_object_unref (win);
2366 }
2367
2368 static void
2369 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2370 {
2371         TnyFolderStore *folder;
2372         GtkWidget *folder_view;
2373         gint response;
2374         gchar *message;
2375         
2376         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2377
2378         folder_view = modest_main_window_get_child_widget (main_window,
2379                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2380         if (!folder_view)
2381                 return;
2382
2383         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2384
2385         /* Show an error if it's an account */
2386         if (!TNY_IS_FOLDER (folder)) {
2387                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2388                                                         _("mail_in_ui_folder_delete_error"));
2389                 g_object_unref (G_OBJECT (folder));
2390                 return ;
2391         }
2392
2393         /* Offer the connection dialog if necessary: */
2394         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2395                 g_object_unref (G_OBJECT (folder));
2396                 return;
2397         }
2398
2399         /* Ask the user */      
2400         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2401                                     tny_folder_get_name (TNY_FOLDER (folder)));
2402         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2403                                                             (const gchar *) message);
2404         g_free (message);
2405
2406         if (response == GTK_RESPONSE_OK) {
2407                 ModestMailOperation *mail_op = 
2408                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2409                                                                        G_OBJECT(main_window),
2410                                                                        modest_ui_actions_delete_folder_error_handler,
2411                                                                        NULL);
2412
2413                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2414                                                  mail_op);
2415                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2416                 g_object_unref (G_OBJECT (mail_op));
2417         }
2418
2419         g_object_unref (G_OBJECT (folder));
2420 }
2421
2422 void 
2423 modest_ui_actions_on_delete_folder (GtkAction *action,
2424                                      ModestMainWindow *main_window)
2425 {
2426         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2427
2428         delete_folder (main_window, FALSE);
2429 }
2430
2431 void 
2432 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2433 {
2434         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2435         
2436         delete_folder (main_window, TRUE);
2437 }
2438
2439
2440 static void
2441 show_error (GtkWidget *parent_widget, const gchar* text)
2442 {
2443         hildon_banner_show_information(parent_widget, NULL, text);
2444         
2445 #if 0
2446         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2447         /*
2448           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2449           (GtkDialogFlags)0,
2450           GTK_MESSAGE_ERROR,
2451           GTK_BUTTONS_OK,
2452           text ));
2453         */
2454                  
2455         gtk_dialog_run (dialog);
2456         gtk_widget_destroy (GTK_WIDGET (dialog));
2457 #endif
2458 }
2459
2460 void
2461 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2462                                          const gchar* server_account_name,
2463                                          gchar **username,
2464                                          gchar **password, 
2465                                          gboolean *cancel, 
2466                                          gboolean *remember,
2467                                          ModestMainWindow *main_window)
2468 {
2469         g_return_if_fail(server_account_name);
2470         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2471         
2472         /* Initalize output parameters: */
2473         if (cancel)
2474                 *cancel = FALSE;
2475                 
2476         if (remember)
2477                 *remember = TRUE;
2478                 
2479 #ifdef MODEST_PLATFORM_MAEMO
2480         /* Maemo uses a different (awkward) button order,
2481          * It should probably just use gtk_alternative_dialog_button_order ().
2482          */
2483         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2484                                               NULL,
2485                                               GTK_DIALOG_MODAL,
2486                                               GTK_STOCK_OK,
2487                                               GTK_RESPONSE_ACCEPT,
2488                                               GTK_STOCK_CANCEL,
2489                                               GTK_RESPONSE_REJECT,
2490                                               NULL);
2491 #else
2492         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2493                                               NULL,
2494                                               GTK_DIALOG_MODAL,
2495                                               GTK_STOCK_CANCEL,
2496                                               GTK_RESPONSE_REJECT,
2497                                               GTK_STOCK_OK,
2498                                               GTK_RESPONSE_ACCEPT,
2499                                               NULL);
2500 #endif /* MODEST_PLATFORM_MAEMO */
2501
2502         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2503         
2504         gchar *server_name = modest_server_account_get_hostname (
2505                 modest_runtime_get_account_mgr(), server_account_name);
2506         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2507                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2508                 *cancel = TRUE;
2509                 return;
2510         }
2511         
2512         /* This causes a warning because the logical ID has no %s in it, 
2513          * though the translation does, but there is not much we can do about that: */
2514         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2515         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2516                             FALSE, FALSE, 0);
2517         g_free (txt);
2518         g_free (server_name);
2519         server_name = NULL;
2520
2521         /* username: */
2522         gchar *initial_username = modest_server_account_get_username (
2523                 modest_runtime_get_account_mgr(), server_account_name);
2524         
2525         GtkWidget *entry_username = gtk_entry_new ();
2526         if (initial_username)
2527                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2528         /* Dim this if a connection has ever succeeded with this username,
2529          * as per the UI spec: */
2530         const gboolean username_known = 
2531                 modest_server_account_get_username_has_succeeded(
2532                         modest_runtime_get_account_mgr(), server_account_name);
2533         gtk_widget_set_sensitive (entry_username, !username_known);
2534         
2535 #ifdef MODEST_PLATFORM_MAEMO
2536         /* Auto-capitalization is the default, so let's turn it off: */
2537         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2538         
2539         /* Create a size group to be used by all captions.
2540          * Note that HildonCaption does not create a default size group if we do not specify one.
2541          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2542         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2543         
2544         GtkWidget *caption = hildon_caption_new (sizegroup, 
2545                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2546         gtk_widget_show (entry_username);
2547         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2548                 FALSE, FALSE, MODEST_MARGIN_HALF);
2549         gtk_widget_show (caption);
2550 #else 
2551         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2552                             TRUE, FALSE, 0);
2553 #endif /* MODEST_PLATFORM_MAEMO */      
2554                             
2555         /* password: */
2556         GtkWidget *entry_password = gtk_entry_new ();
2557         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2558         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2559         
2560 #ifdef MODEST_PLATFORM_MAEMO
2561         /* Auto-capitalization is the default, so let's turn it off: */
2562         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2563                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2564         
2565         caption = hildon_caption_new (sizegroup, 
2566                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2567         gtk_widget_show (entry_password);
2568         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2569                 FALSE, FALSE, MODEST_MARGIN_HALF);
2570         gtk_widget_show (caption);
2571         g_object_unref (sizegroup);
2572 #else 
2573         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2574                             TRUE, FALSE, 0);
2575 #endif /* MODEST_PLATFORM_MAEMO */      
2576                                 
2577 /* This is not in the Maemo UI spec:
2578         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2579         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2580                             TRUE, FALSE, 0);
2581 */
2582
2583         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2584         
2585         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2586                 if (username) {
2587                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2588                         
2589                         modest_server_account_set_username (
2590                                  modest_runtime_get_account_mgr(), server_account_name, 
2591                                  *username);
2592                                  
2593                         const gboolean username_was_changed = 
2594                                 (strcmp (*username, initial_username) != 0);
2595                         if (username_was_changed) {
2596                                 g_warning ("%s: tinymail does not yet support changing the "
2597                                         "username in the get_password() callback.\n", __FUNCTION__);
2598                         }
2599                 }
2600                         
2601                 if (password) {
2602                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2603                         
2604                         /* We do not save the password in the configuration, 
2605                          * because this function is only called for passwords that should 
2606                          * not be remembered:
2607                         modest_server_account_set_password (
2608                                  modest_runtime_get_account_mgr(), server_account_name, 
2609                                  *password);
2610                         */
2611                 }
2612                 
2613                 if (cancel)
2614                         *cancel   = FALSE;
2615                         
2616         } else {
2617                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2618                 
2619                 if (username)
2620                         *username = NULL;
2621                         
2622                 if (password)
2623                         *password = NULL;
2624                         
2625                 if (cancel)
2626                         *cancel   = TRUE;
2627         }
2628
2629 /* This is not in the Maemo UI spec:
2630         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2631                 *remember = TRUE;
2632         else
2633                 *remember = FALSE;
2634 */
2635
2636         gtk_widget_destroy (dialog);
2637         
2638         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2639 }
2640
2641 void
2642 modest_ui_actions_on_cut (GtkAction *action,
2643                           ModestWindow *window)
2644 {
2645         GtkWidget *focused_widget;
2646         GtkClipboard *clipboard;
2647
2648         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2649         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2650         if (GTK_IS_EDITABLE (focused_widget)) {
2651                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2652                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2653                 gtk_clipboard_store (clipboard);
2654         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2655                 GtkTextBuffer *buffer;
2656
2657                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2658                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2659                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2660                 gtk_clipboard_store (clipboard);
2661         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2662                 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2663         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2664                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2665         }
2666 }
2667
2668 void
2669 modest_ui_actions_on_copy (GtkAction *action,
2670                            ModestWindow *window)
2671 {
2672         GtkClipboard *clipboard;
2673         GtkWidget *focused_widget;
2674
2675         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2676         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2677
2678         if (GTK_IS_LABEL (focused_widget)) {
2679                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2680                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2681                 gtk_clipboard_store (clipboard);
2682         } else if (GTK_IS_EDITABLE (focused_widget)) {
2683                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2684                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2685                 gtk_clipboard_store (clipboard);
2686         } else if (GTK_IS_HTML (focused_widget)) {
2687                 gtk_html_copy (GTK_HTML (focused_widget));
2688                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2689                 gtk_clipboard_store (clipboard);
2690         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2691                 GtkTextBuffer *buffer;
2692                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2693                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2694                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2695                 gtk_clipboard_store (clipboard);
2696         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2697                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2698                 TnyIterator *iter = tny_list_create_iterator (header_list);
2699                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2700                 
2701                 gboolean ask = FALSE;
2702                 if (header) {
2703                         TnyFolder *folder = tny_header_get_folder (header);
2704                         TnyAccount *account = tny_folder_get_account (folder);
2705                         const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2706                         /* If it's POP then ask */
2707                         ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2708                                 MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2709                         g_object_unref (account);
2710                         g_object_unref (folder);
2711                         g_object_unref (header);
2712                 }
2713
2714                 g_object_unref (iter);
2715                 
2716                 /* Check that the messages have been previously downloaded */
2717                 gboolean continue_download = TRUE;
2718                 if (ask)
2719                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window), FALSE);
2720                 if (continue_download)
2721                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2722                 g_object_unref (header_list);
2723         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2724                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2725         }    
2726
2727         /* Show information banner */
2728         modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2729         
2730 }
2731
2732 void
2733 modest_ui_actions_on_undo (GtkAction *action,
2734                            ModestWindow *window)
2735 {
2736         ModestEmailClipboard *clipboard = NULL;
2737
2738         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2739                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2740         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2741                 /* Clear clipboard source */
2742                 clipboard = modest_runtime_get_email_clipboard ();
2743                 modest_email_clipboard_clear (clipboard);               
2744         }
2745         else {
2746                 g_return_if_reached ();
2747         }
2748 }
2749
2750 void
2751 modest_ui_actions_on_redo (GtkAction *action,
2752                            ModestWindow *window)
2753 {
2754         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2755                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2756         }
2757         else {
2758                 g_return_if_reached ();
2759         }
2760 }
2761
2762
2763 static void
2764 paste_msgs_cb (const GObject *object, gpointer user_data)
2765 {
2766         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2767         g_return_if_fail (GTK_IS_WIDGET (user_data));
2768         
2769         /* destroy information note */
2770         gtk_widget_destroy (GTK_WIDGET(user_data));
2771 }
2772
2773 static void
2774 paste_as_attachment_free (gpointer data)
2775 {
2776         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
2777
2778         gtk_widget_destroy (helper->banner);
2779         g_object_unref (helper->banner);
2780         g_free (helper);
2781 }
2782
2783 static void
2784 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
2785                             TnyHeader *header,
2786                             TnyMsg *msg,
2787                             gpointer userdata)
2788 {
2789         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
2790         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
2791
2792         if (msg == NULL)
2793                 return;
2794
2795         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
2796         
2797 }
2798
2799 void
2800 modest_ui_actions_on_paste (GtkAction *action,
2801                             ModestWindow *window)
2802 {
2803         GtkWidget *focused_widget = NULL;
2804         GtkWidget *inf_note = NULL;
2805         ModestMailOperation *mail_op = NULL;
2806
2807         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2808         if (GTK_IS_EDITABLE (focused_widget)) {
2809                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2810         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2811                 ModestEmailClipboard *e_clipboard = NULL;
2812                 e_clipboard = modest_runtime_get_email_clipboard ();
2813                 if (modest_email_clipboard_cleared (e_clipboard)) {
2814                         GtkTextBuffer *buffer;
2815                         GtkClipboard *clipboard;
2816
2817                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2818                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2819                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2820                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2821                         ModestMailOperation *mail_op;
2822                         TnyFolder *src_folder;
2823                         TnyList *data;
2824                         gboolean delete;
2825                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
2826                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
2827                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
2828                                                                            _CS("ckct_nw_pasting"));
2829                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
2830                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2831                                                              G_OBJECT (window));
2832                         if (helper->banner != NULL) {
2833                                 g_object_ref (G_OBJECT (helper->banner));
2834                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
2835                                 gtk_widget_show (GTK_WIDGET (helper->banner));
2836                         }
2837
2838                         if (data != NULL) {
2839                                 modest_mail_operation_get_msgs_full (mail_op, 
2840                                                                      data,
2841                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
2842                                                                      helper,
2843                                                                      paste_as_attachment_free);
2844                         }
2845                 }
2846         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2847                 ModestEmailClipboard *clipboard = NULL;
2848                 TnyFolder *src_folder = NULL;
2849                 TnyFolderStore *folder_store = NULL;
2850                 TnyList *data = NULL;           
2851                 gboolean delete = FALSE;
2852                 
2853                 /* Check clipboard source */
2854                 clipboard = modest_runtime_get_email_clipboard ();
2855                 if (modest_email_clipboard_cleared (clipboard)) 
2856                         return;
2857                 
2858                 /* Get elements to paste */
2859                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
2860
2861                 /* Create a new mail operation */
2862                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
2863                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2864                                                  mail_op);
2865                 
2866                 /* Get destination folder */
2867                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
2868
2869                 /* Launch notification */
2870                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
2871                                                              _CS("ckct_nw_pasting"));
2872                 if (inf_note != NULL)  {
2873                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
2874                         gtk_widget_show (GTK_WIDGET(inf_note));
2875                 }
2876
2877                 /* transfer messages  */
2878                 if (data != NULL) {
2879                         modest_mail_operation_xfer_msgs (mail_op, 
2880                                                          data,
2881                                                          TNY_FOLDER (folder_store),
2882                                                          delete,
2883                                                          paste_msgs_cb,
2884                                                          inf_note);
2885                         
2886                 } else if (src_folder != NULL) {                        
2887                         modest_mail_operation_xfer_folder (mail_op, 
2888                                                            src_folder,
2889                                                            folder_store,
2890                                                            delete,
2891                                                            paste_msgs_cb,
2892                                                            inf_note);
2893                 }
2894
2895                 /* Free */
2896                 if (data != NULL) 
2897                         g_object_unref (data);
2898                 if (src_folder != NULL) 
2899                         g_object_unref (src_folder);
2900                 if (folder_store != NULL) 
2901                         g_object_unref (folder_store);
2902         }
2903 }
2904
2905
2906 void
2907 modest_ui_actions_on_select_all (GtkAction *action,
2908                                  ModestWindow *window)
2909 {
2910         GtkWidget *focused_widget;
2911
2912         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2913         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2914                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2915         } else if (GTK_IS_LABEL (focused_widget)) {
2916                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2917         } else if (GTK_IS_EDITABLE (focused_widget)) {
2918                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2919         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2920                 GtkTextBuffer *buffer;
2921                 GtkTextIter start, end;
2922
2923                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2924                 gtk_text_buffer_get_start_iter (buffer, &start);
2925                 gtk_text_buffer_get_end_iter (buffer, &end);
2926                 gtk_text_buffer_select_range (buffer, &start, &end);
2927         } else if (GTK_IS_HTML (focused_widget)) {
2928                 gtk_html_select_all (GTK_HTML (focused_widget));
2929         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2930                 GtkWidget *header_view = focused_widget;
2931                 GtkTreeSelection *selection = NULL;
2932                 
2933                 if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
2934                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2935                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2936                                 
2937                 /* Select all messages */
2938                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2939                 gtk_tree_selection_select_all (selection);
2940
2941                 /* Set focuse on header view */
2942                 gtk_widget_grab_focus (header_view);
2943         }
2944
2945 }
2946
2947 void
2948 modest_ui_actions_on_mark_as_read (GtkAction *action,
2949                                    ModestWindow *window)
2950 {       
2951         g_return_if_fail (MODEST_IS_WINDOW(window));
2952                 
2953         /* Mark each header as read */
2954         do_headers_action (window, headers_action_mark_as_read, NULL);
2955 }
2956
2957 void
2958 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2959                                      ModestWindow *window)
2960 {       
2961         g_return_if_fail (MODEST_IS_WINDOW(window));
2962                 
2963         /* Mark each header as read */
2964         do_headers_action (window, headers_action_mark_as_unread, NULL);
2965 }
2966
2967 void
2968 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2969                                   GtkRadioAction *selected,
2970                                   ModestWindow *window)
2971 {
2972         gint value;
2973
2974         value = gtk_radio_action_get_current_value (selected);
2975         if (MODEST_IS_WINDOW (window)) {
2976                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2977         }
2978 }
2979
2980 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2981                                                         GtkRadioAction *selected,
2982                                                         ModestWindow *window)
2983 {
2984         TnyHeaderFlags flags;
2985         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2986
2987         flags = gtk_radio_action_get_current_value (selected);
2988         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2989 }
2990
2991 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2992                                                            GtkRadioAction *selected,
2993                                                            ModestWindow *window)
2994 {
2995         gint file_format;
2996
2997         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2998
2999         file_format = gtk_radio_action_get_current_value (selected);
3000         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3001 }
3002
3003
3004 void     
3005 modest_ui_actions_on_zoom_plus (GtkAction *action,
3006                                 ModestWindow *window)
3007 {
3008         g_return_if_fail (MODEST_IS_WINDOW (window));
3009
3010         modest_window_zoom_plus (MODEST_WINDOW (window));
3011 }
3012
3013 void     
3014 modest_ui_actions_on_zoom_minus (GtkAction *action,
3015                                  ModestWindow *window)
3016 {
3017         g_return_if_fail (MODEST_IS_WINDOW (window));
3018
3019         modest_window_zoom_minus (MODEST_WINDOW (window));
3020 }
3021
3022 void     
3023 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3024                                            ModestWindow *window)
3025 {
3026         ModestWindowMgr *mgr;
3027         gboolean fullscreen, active;
3028         g_return_if_fail (MODEST_IS_WINDOW (window));
3029
3030         mgr = modest_runtime_get_window_mgr ();
3031
3032         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3033         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3034
3035         if (active != fullscreen) {
3036                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3037                 gtk_window_present (GTK_WINDOW (window));
3038         }
3039 }
3040
3041 void
3042 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3043                                         ModestWindow *window)
3044 {
3045         ModestWindowMgr *mgr;
3046         gboolean fullscreen;
3047
3048         g_return_if_fail (MODEST_IS_WINDOW (window));
3049
3050         mgr = modest_runtime_get_window_mgr ();
3051         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3052         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3053
3054         gtk_window_present (GTK_WINDOW (window));
3055 }
3056
3057 /* 
3058  * Used by modest_ui_actions_on_details to call do_headers_action 
3059  */
3060 static void
3061 headers_action_show_details (TnyHeader *header, 
3062                              ModestWindow *window,
3063                              gpointer user_data)
3064
3065 {
3066         GtkWidget *dialog;
3067         
3068         /* Create dialog */
3069         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3070
3071         /* Run dialog */
3072         gtk_widget_show_all (dialog);
3073         gtk_dialog_run (GTK_DIALOG (dialog));
3074
3075         gtk_widget_destroy (dialog);
3076 }
3077
3078 /*
3079  * Show the folder details in a ModestDetailsDialog widget
3080  */
3081 static void
3082 show_folder_details (TnyFolder *folder, 
3083                      GtkWindow *window)
3084 {
3085         GtkWidget *dialog;
3086         
3087         /* Create dialog */
3088         dialog = modest_details_dialog_new_with_folder (window, folder);
3089
3090         /* Run dialog */
3091         gtk_widget_show_all (dialog);
3092         gtk_dialog_run (GTK_DIALOG (dialog));
3093
3094         gtk_widget_destroy (dialog);
3095 }
3096
3097 /*
3098  * Show the header details in a ModestDetailsDialog widget
3099  */
3100 void     
3101 modest_ui_actions_on_details (GtkAction *action, 
3102                               ModestWindow *win)
3103 {
3104         TnyList * headers_list;
3105         TnyIterator *iter;
3106         TnyHeader *header;              
3107
3108         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3109                 TnyMsg *msg;
3110
3111                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3112                 if (!msg)
3113                         return;
3114                 g_object_unref (msg);           
3115
3116                 headers_list = get_selected_headers (win);
3117                 if (!headers_list)
3118                         return;
3119
3120                 iter = tny_list_create_iterator (headers_list);
3121
3122                 header = TNY_HEADER (tny_iterator_get_current (iter));
3123                 if (header) {
3124                         headers_action_show_details (header, win, NULL);
3125                         g_object_unref (header);
3126                 }
3127
3128                 g_object_unref (iter);
3129                 g_object_unref (headers_list);
3130
3131         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3132                 GtkWidget *folder_view, *header_view;
3133
3134                 /* Check which widget has the focus */
3135                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3136                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
3137                 if (gtk_widget_is_focus (folder_view)) {
3138                         TnyFolderStore *folder_store
3139                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3140                         if (!folder_store) {
3141                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3142                                 return; 
3143                         }
3144                         /* Show only when it's a folder */
3145                         /* This function should not be called for account items, 
3146                          * because we dim the menu item for them. */
3147                         if (TNY_IS_FOLDER (folder_store)) {
3148                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3149                         }
3150
3151                         g_object_unref (folder_store);
3152
3153                 } else {
3154                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3155                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3156                         /* Show details of each header */
3157                         do_headers_action (win, headers_action_show_details, header_view);
3158                 }
3159         }
3160 }
3161
3162 void     
3163 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3164                                      ModestMsgEditWindow *window)
3165 {
3166         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3167
3168         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3169 }
3170
3171 void     
3172 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3173                                       ModestMsgEditWindow *window)
3174 {
3175         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3176
3177         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3178 }
3179
3180 void
3181 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3182                                        ModestMainWindow *main_window)
3183 {
3184         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3185
3186         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3187                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3188         else
3189                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3190 }
3191
3192 void 
3193 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3194                                      ModestWindow *window)
3195 {
3196         gboolean active, fullscreen = FALSE;
3197         ModestWindowMgr *mgr;
3198
3199         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3200
3201         /* Check if we want to toggle the toolbar vuew in fullscreen
3202            or normal mode */
3203         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3204                      "ViewShowToolbarFullScreen")) {
3205                 fullscreen = TRUE;
3206         }
3207
3208         /* Toggle toolbar */
3209         mgr = modest_runtime_get_window_mgr ();
3210         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
3211 }
3212
3213 void     
3214 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3215                                            ModestMsgEditWindow *window)
3216 {
3217         modest_msg_edit_window_select_font (window);
3218 }
3219
3220 void
3221 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3222                                                   const gchar *display_name,
3223                                                   GtkWindow *window)
3224 {
3225         /* Do not change the application name if the widget has not
3226            the focus. This callback could be called even if the folder
3227            view has not the focus, because the handled signal could be
3228            emitted when the folder view is redrawn */
3229         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3230                 if (display_name)
3231                         gtk_window_set_title (window, display_name);
3232                 else
3233                         gtk_window_set_title (window, " ");
3234         }
3235 }
3236
3237 void
3238 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3239 {
3240         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3241         modest_msg_edit_window_select_contacts (window);
3242 }
3243
3244 void
3245 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3246 {
3247         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3248         modest_msg_edit_window_check_names (window, FALSE);
3249 }
3250
3251 static void
3252 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3253 {
3254         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3255                                          GTK_WIDGET (user_data));
3256 }
3257
3258 static GtkWidget*
3259 create_move_to_dialog (GtkWindow *win,
3260                        GtkWidget *folder_view,
3261                        GtkWidget **tree_view)
3262 {
3263         GtkWidget *dialog, *scroll;
3264         GtkWidget *new_button;
3265
3266         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3267                                               GTK_WINDOW (win),
3268                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3269                                               NULL);
3270
3271         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
3272         /* We do this manually so GTK+ does not associate a response ID for
3273          * the button. */
3274         new_button = gtk_button_new_from_stock (GTK_STOCK_NEW);
3275         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3276         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
3277
3278         /* Create scrolled window */
3279         scroll = gtk_scrolled_window_new (NULL, NULL);
3280         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3281                                          GTK_POLICY_AUTOMATIC,
3282                                          GTK_POLICY_AUTOMATIC);
3283
3284         /* Create folder view */
3285         *tree_view = modest_platform_create_folder_view (NULL);
3286
3287         g_signal_connect (G_OBJECT (new_button), "clicked", G_CALLBACK(create_move_to_dialog_on_new_folder), *tree_view);
3288
3289         /* It could happen that we're trying to move a message from a
3290            window (msg window for example) after the main window was
3291            closed, so we can not just get the model of the folder
3292            view */
3293         if (MODEST_IS_FOLDER_VIEW (folder_view))
3294                 gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
3295                                          gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
3296         else
3297                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3298                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3299
3300         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3301         
3302         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3303
3304         /* Add scroll to dialog */
3305         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3306                             scroll, TRUE, TRUE, 0);
3307
3308         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3309         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3310
3311         return dialog;
3312 }
3313
3314 /*
3315  * Returns TRUE if at least one of the headers of the list belongs to
3316  * a message that has been fully retrieved.
3317  */
3318 static gboolean
3319 has_retrieved_msgs (TnyList *list)
3320 {
3321         TnyIterator *iter;
3322         gboolean found = FALSE;
3323
3324         iter = tny_list_create_iterator (list);
3325         while (tny_iterator_is_done (iter) && !found) {
3326                 TnyHeader *header;
3327                 TnyHeaderFlags flags = 0;
3328
3329                 header = TNY_HEADER (tny_iterator_get_current (iter));
3330                 if (header) {
3331                         flags = tny_header_get_flags (header);
3332                         if (!(flags & TNY_HEADER_FLAG_PARTIAL))
3333                                 found = TRUE;
3334
3335                         g_object_unref (header);
3336                 }
3337
3338                 if (!found)
3339                         tny_iterator_next (iter);
3340         }
3341         g_object_unref (iter);
3342
3343         return found;
3344 }
3345
3346 /*
3347  * Shows a confirmation dialog to the user when we're moving messages
3348  * from a remote server to the local storage. Returns the dialog
3349  * response. If it's other kind of movement the it always returns
3350  * GTK_RESPONSE_OK
3351  */
3352 static gint
3353 msgs_move_to_confirmation (GtkWindow *win,
3354                            TnyFolder *dest_folder,
3355                            TnyList *headers)
3356 {
3357         gint response = GTK_RESPONSE_OK;
3358
3359         /* If the destination is a local folder */
3360         if (modest_tny_folder_is_local_folder (dest_folder)) {
3361                 TnyFolder *src_folder = NULL;
3362                 TnyIterator *iter = NULL;
3363                 TnyHeader *header = NULL;
3364
3365                 /* Get source folder */
3366                 iter = tny_list_create_iterator (headers);
3367                 header = TNY_HEADER (tny_iterator_get_current (iter));
3368                 if (header) {
3369                         src_folder = tny_header_get_folder (header);
3370                         g_object_unref (header);
3371                 }
3372
3373                 g_object_unref (iter);
3374
3375                 /* if no src_folder, message may be an attahcment */
3376                 if (src_folder == NULL) 
3377                         return GTK_RESPONSE_CANCEL;
3378
3379                 /* If the source is a remote folder */
3380                 if (!modest_tny_folder_is_local_folder (src_folder)) {
3381                         const gchar *message;
3382                         
3383                         if (has_retrieved_msgs (headers))
3384                                 message = ngettext ("mcen_nc_move_retrieve", "mcen_nc_move_retrieves",
3385                                                     tny_list_get_length (headers));
3386                         else 
3387                                 message = ngettext ("mcen_nc_move_header", "mcen_nc_move_headers",
3388                                                     tny_list_get_length (headers));
3389
3390                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
3391                                                                             (const gchar *) message);
3392                 }
3393                 
3394                 g_object_unref (src_folder);
3395         }
3396         
3397         return response;
3398 }
3399
3400
3401
3402 static void
3403 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3404 {
3405         ModestMsgViewWindow *self = NULL;
3406
3407         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3408         self = MODEST_MSG_VIEW_WINDOW (object);
3409         
3410         if (!modest_msg_view_window_select_next_message (self))
3411                 if (!modest_msg_view_window_select_previous_message (self))
3412                         /* No more messages to view, so close this window */
3413                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3414 }
3415
3416 void
3417 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3418                                              gpointer user_data)
3419 {
3420         GObject *win = modest_mail_operation_get_source (mail_op);
3421         const GError *error = NULL;
3422         const gchar *message = NULL;
3423         
3424         /* Get error message */
3425         error = modest_mail_operation_get_error (mail_op);
3426         if (error != NULL && error->message != NULL) {
3427                 message = error->message;
3428         } else {
3429                 message = _("mail_in_ui_folder_move_target_error");
3430         }
3431         
3432         /* Show notification dialog */
3433         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3434         g_object_unref (win);
3435 }
3436
3437 void
3438 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3439                                               gpointer user_data)
3440 {
3441         GObject *win = modest_mail_operation_get_source (mail_op);
3442         const GError *error = modest_mail_operation_get_error (mail_op);
3443
3444         g_return_if_fail (error != NULL);
3445         if (error->message != NULL)             
3446                 g_printerr ("modest: %s\n", error->message);
3447         else
3448                 g_printerr ("modest: unkonw error on send&receive operation");
3449
3450         /* Show error message */
3451 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3452 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3453 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3454 /*      else  */
3455 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3456 /*                                                      _CS("sfil_ib_unable_to_send")); */
3457         g_object_unref (win);
3458 }
3459
3460 static void
3461 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3462                        TnyHeader *header, 
3463                        TnyMsg *msg, 
3464                        gpointer user_data)
3465 {
3466         TnyList *parts;
3467         TnyIterator *iter;
3468         gint pending_purges = 0;
3469         gboolean some_purged = FALSE;
3470         ModestWindow *win = MODEST_WINDOW (user_data);
3471         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3472
3473         /* If there was any error */
3474         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
3475                 modest_window_mgr_unregister_header (mgr, header);
3476                 return;
3477         }
3478
3479         /* Once the message has been retrieved for purging, we check if
3480          * it's all ok for purging */
3481
3482         parts = tny_simple_list_new ();
3483         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3484         iter = tny_list_create_iterator (parts);
3485
3486         while (!tny_iterator_is_done (iter)) {
3487                 TnyMimePart *part;
3488                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3489                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
3490                         if (tny_mime_part_is_purged (part))
3491                                 some_purged = TRUE;
3492                         else
3493                                 pending_purges++;
3494                 }
3495
3496                 if (part)
3497                         g_object_unref (part);
3498
3499                 tny_iterator_next (iter);
3500         }
3501
3502         if (pending_purges>0) {
3503                 gint response;
3504                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3505
3506                 if (response == GTK_RESPONSE_OK) {
3507                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3508                         tny_iterator_first (iter);
3509                         while (!tny_iterator_is_done (iter)) {
3510                                 TnyMimePart *part;
3511                                 
3512                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3513                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
3514                                         tny_mime_part_set_purged (part);
3515
3516                                 if (part)
3517                                         g_object_unref (part);
3518
3519                                 tny_iterator_next (iter);
3520                         }
3521                         
3522                         tny_msg_rewrite_cache (msg);
3523                 }
3524         } else {
3525                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3526         }
3527
3528         /* remove attachments */
3529         tny_iterator_first (iter);
3530         while (!tny_iterator_is_done (iter)) {
3531                 TnyMimePart *part;
3532                         
3533                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3534                 if (part) {
3535                         /* One for the reference given by tny_iterator_get_current(): */
3536                         g_object_unref (part);
3537
3538                         /* TODO: Is this meant to remove the attachment by doing another unref()? 
3539                          * Otherwise, this seems useless. */
3540                 }
3541
3542                 tny_iterator_next (iter);
3543         }
3544         modest_window_mgr_unregister_header (mgr, header);
3545
3546         g_object_unref (iter);
3547         g_object_unref (parts);
3548 }
3549
3550 static void
3551 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3552                                                      ModestMainWindow *win)
3553 {
3554         GtkWidget *header_view;
3555         TnyList *header_list;
3556         TnyIterator *iter;
3557         TnyHeader *header;
3558         TnyHeaderFlags flags;
3559         ModestWindow *msg_view_window =  NULL;
3560         gboolean found;
3561
3562         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3563
3564         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3565                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3566
3567         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3568
3569         if (tny_list_get_length (header_list) == 1) {
3570                 iter = tny_list_create_iterator (header_list);
3571                 header = TNY_HEADER (tny_iterator_get_current (iter));
3572                 g_object_unref (iter);
3573         } else {
3574                 return;
3575         }
3576
3577         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3578                                                           header, &msg_view_window);
3579         flags = tny_header_get_flags (header);
3580         if (!(flags & TNY_HEADER_FLAG_CACHED))
3581                 return;
3582         if (found) {
3583                 if (msg_view_window != NULL) 
3584                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3585                 else {
3586                         /* do nothing; uid was registered before, so window is probably on it's way */
3587                         g_warning ("debug: header %p has already been registered", header);
3588                 }
3589         } else {
3590                 ModestMailOperation *mail_op = NULL;
3591                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3592                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3593                                                                          G_OBJECT (win),
3594                                                                          modest_ui_actions_get_msgs_full_error_handler,
3595                                                                          NULL);
3596                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3597                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3598                 
3599                 g_object_unref (mail_op);
3600         }
3601         if (header)
3602                 g_object_unref (header);
3603         if (header_list)
3604                 g_object_unref (header_list);
3605 }
3606
3607 /**
3608  * Utility function that transfer messages from both the main window
3609  * and the msg view window when using the "Move to" dialog
3610  */
3611 static void
3612 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
3613                                               ModestWindow *win)
3614 {
3615         TnyList *headers = NULL;
3616         gint response = 0;
3617
3618         if (!TNY_IS_FOLDER (dst_folder)) {
3619                 modest_platform_information_banner (GTK_WIDGET (win),
3620                                                     NULL,
3621                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
3622                 return;
3623         }
3624
3625         /* Get selected headers */
3626         headers = get_selected_headers (MODEST_WINDOW (win));
3627
3628         /* Ask for user confirmation */
3629         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3630                                               TNY_FOLDER (dst_folder), 
3631                                               headers);
3632
3633         /* Transfer messages */
3634         if (response == GTK_RESPONSE_OK) {
3635                 ModestMailOperation *mail_op = 
3636                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3637                                                                        G_OBJECT(win),
3638                                                                        modest_ui_actions_move_folder_error_handler,
3639                                                                        NULL);
3640                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3641                                                  mail_op);
3642
3643                 modest_mail_operation_xfer_msgs (mail_op, 
3644                                                  headers,
3645                                                  TNY_FOLDER (dst_folder),
3646                                                  TRUE,
3647                                                  (MODEST_IS_MSG_VIEW_WINDOW (win)) ? transfer_msgs_from_viewer_cb : NULL,
3648                                                  NULL);
3649
3650                 g_object_unref (G_OBJECT (mail_op));
3651         }
3652         g_object_unref (headers);
3653 }
3654
3655
3656 /*
3657  * UI handler for the "Move to" action when invoked from the
3658  * ModestMainWindow
3659  */
3660 static void 
3661 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
3662                                           GtkWidget *folder_view,
3663                                           TnyFolderStore *dst_folder,
3664                                           ModestMainWindow *win)
3665 {
3666         GtkWidget *header_view = NULL;
3667         ModestMailOperation *mail_op = NULL;
3668         TnyFolderStore *src_folder;
3669
3670         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3671
3672         /* Get the source folder */
3673         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3674         
3675         /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
3676         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
3677                                                                       src_folder))
3678                 goto end;
3679
3680         /* Get header view */
3681         header_view = 
3682                 modest_main_window_get_child_widget (win, MODEST_WIDGET_TYPE_HEADER_VIEW);
3683
3684         /* Get folder or messages to transfer */
3685         if (gtk_widget_is_focus (folder_view)) {
3686
3687                 /* Allow only to transfer folders to the local root folder */
3688                 if (TNY_IS_ACCOUNT (dst_folder) && 
3689                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder))
3690                         goto end;
3691                 
3692                 /* Clean folder on header view before moving it */
3693                 modest_header_view_clear (MODEST_HEADER_VIEW (header_view)); 
3694
3695                 if (TNY_IS_FOLDER (src_folder)) {
3696                         mail_op = 
3697                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3698                                                                                G_OBJECT(win),
3699                                                                                modest_ui_actions_move_folder_error_handler,
3700                                                                                NULL);
3701                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3702                                                          mail_op);
3703
3704                         modest_mail_operation_xfer_folder (mail_op, 
3705                                                            TNY_FOLDER (src_folder),
3706                                                            dst_folder,
3707                                                            TRUE, NULL, NULL);
3708                         /* Unref mail operation */
3709                         g_object_unref (G_OBJECT (mail_op));
3710                 } else {
3711                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);       
3712                 }
3713         } else if (gtk_widget_is_focus (header_view)) {
3714                 /* Transfer messages */
3715                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3716         }
3717         
3718  end:
3719     if (src_folder)
3720         g_object_unref (src_folder);
3721 }
3722
3723
3724 /*
3725  * UI handler for the "Move to" action when invoked from the
3726  * ModestMsgViewWindow
3727  */
3728 static void 
3729 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
3730                                               TnyFolderStore *dst_folder,
3731                                               ModestMsgViewWindow *win)
3732 {
3733         TnyHeader *header = NULL;
3734         TnyFolder *src_folder;
3735
3736         /* Create header list */
3737         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
3738         src_folder = tny_header_get_folder(header);
3739         g_object_unref (header);
3740
3741         /* Transfer the message */
3742         if (modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (src_folder)))
3743                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3744
3745         g_object_unref (src_folder);
3746 }
3747
3748 void 
3749 modest_ui_actions_on_move_to (GtkAction *action, 
3750                               ModestWindow *win)
3751 {
3752         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
3753         gint result = 0;
3754         TnyFolderStore *dst_folder = NULL;
3755         ModestMainWindow *main_window;
3756
3757         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
3758                           MODEST_IS_MSG_VIEW_WINDOW (win));
3759
3760         /* Get the main window if exists */
3761         if (MODEST_IS_MAIN_WINDOW (win))
3762                 main_window = MODEST_MAIN_WINDOW (win);
3763         else
3764                 main_window = 
3765                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
3766
3767         /* Get the folder view widget if exists */
3768         if (main_window)
3769                 folder_view = modest_main_window_get_child_widget (main_window,
3770                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
3771         else
3772                 folder_view = NULL;
3773
3774         /* Create and run the dialog */
3775         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
3776         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
3777         result = gtk_dialog_run (GTK_DIALOG(dialog));
3778         g_object_ref (tree_view);
3779         gtk_widget_destroy (dialog);
3780
3781         if (result != GTK_RESPONSE_ACCEPT)
3782                 return;
3783
3784         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
3785         /* Offer the connection dialog if necessary: */
3786         if (modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
3787                                                                       dst_folder)) {
3788
3789                 /* Do window specific stuff */
3790                 if (MODEST_IS_MAIN_WINDOW (win))
3791                         modest_ui_actions_on_main_window_move_to (action,
3792                                                                   folder_view,
3793                                                                   dst_folder,
3794                                                                   MODEST_MAIN_WINDOW (win));
3795                 else
3796                         modest_ui_actions_on_msg_view_window_move_to (action,
3797                                                                       dst_folder,
3798                                                                       MODEST_MSG_VIEW_WINDOW (win));
3799         }
3800         if (dst_folder)
3801                 g_object_unref (dst_folder);
3802 }
3803
3804 /*
3805  * Calls #HeadersFunc for each header already selected in the main
3806  * window or the message currently being shown in the msg view window
3807  */
3808 static void
3809 do_headers_action (ModestWindow *win, 
3810                    HeadersFunc func,
3811                    gpointer user_data)
3812 {
3813         TnyList *headers_list = NULL;
3814         TnyIterator *iter = NULL;
3815         TnyHeader *header = NULL;
3816         TnyFolder *folder = NULL;
3817
3818         /* Get headers */
3819         headers_list = get_selected_headers (win);
3820         if (!headers_list)
3821                 return;
3822
3823         /* Get the folder */
3824         iter = tny_list_create_iterator (headers_list);
3825         header = TNY_HEADER (tny_iterator_get_current (iter));
3826         if (header) {
3827                 folder = tny_header_get_folder (header);
3828                 g_object_unref (header);
3829         }
3830
3831         /* Call the function for each header */
3832         while (!tny_iterator_is_done (iter)) {
3833                 header = TNY_HEADER (tny_iterator_get_current (iter));
3834                 func (header, win, user_data);
3835                 g_object_unref (header);
3836                 tny_iterator_next (iter);
3837         }
3838
3839         /* Trick: do a poke status in order to speed up the signaling
3840            of observers */
3841         tny_folder_poke_status (folder);
3842
3843         /* Frees */
3844         g_object_unref (folder);
3845         g_object_unref (iter);
3846         g_object_unref (headers_list);
3847 }
3848
3849 void 
3850 modest_ui_actions_view_attachment (GtkAction *action,
3851                                    ModestWindow *window)
3852 {
3853         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3854                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
3855         } else {
3856                 /* not supported window for this action */
3857                 g_return_if_reached ();
3858         }
3859 }
3860
3861 void
3862 modest_ui_actions_save_attachments (GtkAction *action,
3863                                     ModestWindow *window)
3864 {
3865         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3866                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
3867         } else {
3868                 /* not supported window for this action */
3869                 g_return_if_reached ();
3870         }
3871 }
3872
3873 void
3874 modest_ui_actions_remove_attachments (GtkAction *action,
3875                                       ModestWindow *window)
3876 {
3877         if (MODEST_IS_MAIN_WINDOW (window)) {
3878                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
3879         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3880                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
3881         } else {
3882                 /* not supported window for this action */
3883                 g_return_if_reached ();
3884         }
3885 }
3886
3887 void 
3888 modest_ui_actions_on_settings (GtkAction *action, 
3889                                ModestWindow *win)
3890 {
3891         GtkWidget *dialog;
3892
3893         dialog = modest_platform_get_global_settings_dialog ();
3894         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
3895         gtk_widget_show_all (dialog);
3896
3897         gtk_dialog_run (GTK_DIALOG (dialog));
3898
3899         gtk_widget_destroy (dialog);
3900 }
3901
3902 void 
3903 modest_ui_actions_on_help (GtkAction *action, 
3904                            ModestWindow *win)
3905 {
3906         const gchar *help_id = NULL;
3907
3908         if (MODEST_IS_MAIN_WINDOW (win)) {
3909                 const gchar *action_name;
3910                 action_name = gtk_action_get_name (action);
3911
3912                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
3913                     !strcmp (action_name, "HeaderViewCSMHelp")) {
3914                         GtkWidget *folder_view;
3915                         TnyFolderStore *folder_store;
3916                         /* Get selected folder */
3917                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3918                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3919                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3920
3921                         /* Switch help_id */
3922                         if (TNY_IS_FOLDER (folder_store)) {
3923                                 switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
3924                                 case TNY_FOLDER_TYPE_NORMAL:
3925                                         help_id = "applications_email_managefolders";
3926                                         break;
3927                                 case TNY_FOLDER_TYPE_INBOX:
3928                                         help_id = "applications_email_inbox";
3929                                         break;
3930                                 case TNY_FOLDER_TYPE_OUTBOX:
3931                                         help_id = "applications_email_outbox";
3932                                         break;
3933                                 case TNY_FOLDER_TYPE_SENT:
3934                                         help_id = "applications_email_sent";
3935                                         break;
3936                                 case TNY_FOLDER_TYPE_DRAFTS:
3937                                         help_id = "applications_email_drafts";
3938                                         break;
3939                                 case TNY_FOLDER_TYPE_ARCHIVE:
3940                                         help_id = "applications_email_managefolders";
3941                                         break;
3942                                 default:
3943                                         help_id = "applications_email_managefolders";
3944                                 }
3945                         } else {
3946                                 help_id = "applications_email_mainview";        
3947                         }
3948                         g_object_unref (folder_store);
3949                 } else {
3950                         help_id = "applications_email_mainview";        
3951                 }
3952         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3953                 help_id = "applications_email_viewer";
3954         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
3955                 help_id = "applications_email_editor";
3956
3957         modest_platform_show_help (GTK_WINDOW (win), help_id);
3958 }
3959
3960 void 
3961 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
3962                                             ModestWindow *window)
3963 {
3964         ModestMailOperation *mail_op;
3965         TnyList *headers;
3966
3967         /* Get headers */
3968         headers = get_selected_headers (window);
3969         if (!headers)
3970                 return;
3971
3972         /* Create mail operation */
3973         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3974                                                                  G_OBJECT (window),
3975                                                                  modest_ui_actions_get_msgs_full_error_handler, 
3976                                                                  NULL);
3977         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3978         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
3979
3980         /* Frees */
3981         g_object_unref (headers);
3982         g_object_unref (mail_op);
3983 }
3984
3985 void
3986 modest_ui_actions_on_email_menu_activated (GtkAction *action,
3987                                           ModestWindow *window)
3988 {
3989         g_return_if_fail (MODEST_IS_WINDOW (window));
3990
3991         /* Update dimmed */     
3992         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3993 }
3994
3995 void
3996 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
3997                                           ModestWindow *window)
3998 {
3999         g_return_if_fail (MODEST_IS_WINDOW (window));
4000
4001         /* Update dimmed */     
4002         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4003 }
4004
4005 void
4006 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4007                                           ModestWindow *window)
4008 {
4009         g_return_if_fail (MODEST_IS_WINDOW (window));
4010
4011         /* Update dimmed */     
4012         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4013 }
4014
4015 void
4016 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4017                                           ModestWindow *window)
4018 {
4019         g_return_if_fail (MODEST_IS_WINDOW (window));
4020
4021         /* Update dimmed */     
4022         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4023 }
4024
4025 void
4026 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4027                                           ModestWindow *window)
4028 {
4029         g_return_if_fail (MODEST_IS_WINDOW (window));
4030
4031         /* Update dimmed */     
4032         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4033 }
4034
4035 void
4036 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4037                                                  ModestWindow *window)
4038 {
4039         g_return_if_fail (MODEST_IS_WINDOW (window));
4040
4041         /* Update dimmed */     
4042         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4043 }
4044
4045 void
4046 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4047                                                      ModestWindow *window)
4048 {
4049         g_return_if_fail (MODEST_IS_WINDOW (window));
4050
4051         /* Update dimmed */     
4052         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4053 }
4054
4055 void
4056 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4057                                                      ModestWindow *window)
4058 {
4059         g_return_if_fail (MODEST_IS_WINDOW (window));
4060
4061         /* Update dimmed */     
4062         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4063 }
4064
4065 void
4066 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4067 {
4068         g_return_if_fail (MODEST_IS_WINDOW (window));
4069
4070         /* Update dimmed */     
4071         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4072 }
4073
4074 void
4075 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4076 {
4077         g_return_if_fail (MODEST_IS_WINDOW (window));
4078
4079         modest_platform_show_search_messages (GTK_WINDOW (window));
4080 }
4081
4082 void     
4083 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4084 {
4085         g_return_if_fail (MODEST_IS_WINDOW (win));
4086         modest_platform_show_addressbook (GTK_WINDOW (win));
4087 }
4088
4089
4090 void
4091 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4092                                           ModestWindow *window)
4093 {
4094         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4095
4096         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4097 }
4098
4099 static void 
4100 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
4101                                    ModestMailOperationState *state,
4102                                    gpointer user_data)
4103 {
4104         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
4105
4106         /* Set send/receive operation finished */       
4107         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
4108                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
4109         
4110 }
4111
4112