* Fixes hangs when moving messages between folders while being offline
[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 #include "modest-protocol-info.h"
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include "modest-debug.h"
48 #include <tny-mime-part.h>
49 #include <tny-camel-folder.h>
50 #include <tny-camel-imap-folder.h>
51 #include <tny-camel-pop-folder.h>
52
53 #ifdef MODEST_PLATFORM_MAEMO
54 #include "maemo/modest-osso-state-saving.h"
55 #include "maemo/modest-hildon-includes.h"
56 #include "maemo/modest-connection-specific-smtp-window.h"
57 #endif /* MODEST_PLATFORM_MAEMO */
58 #include <modest-utils.h>
59
60 #include "widgets/modest-ui-constants.h"
61 #include <widgets/modest-main-window.h>
62 #include <widgets/modest-msg-view-window.h>
63 #include <widgets/modest-account-view-window.h>
64 #include <widgets/modest-details-dialog.h>
65 #include <widgets/modest-attachments-view.h>
66 #include "widgets/modest-folder-view.h"
67 #include "widgets/modest-global-settings-dialog.h"
68 #include "modest-account-mgr-helpers.h"
69 #include "modest-mail-operation.h"
70 #include "modest-text-utils.h"
71
72 #ifdef MODEST_HAVE_EASYSETUP
73 #include "easysetup/modest-easysetup-wizard.h"
74 #endif /* MODEST_HAVE_EASYSETUP */
75
76 #include <modest-widget-memory.h>
77 #include <tny-error.h>
78 #include <tny-simple-list.h>
79 #include <tny-msg-view.h>
80 #include <tny-device.h>
81 #include <tny-merge-folder.h>
82
83 #include <gtkhtml/gtkhtml.h>
84
85 typedef struct _GetMsgAsyncHelper {     
86         ModestWindow *window;
87         ModestMailOperation *mail_op;
88         TnyIterator *iter;
89         guint num_ops;
90         GFunc func;     
91         gpointer user_data;
92 } GetMsgAsyncHelper;
93
94 typedef enum _ReplyForwardAction {
95         ACTION_REPLY,
96         ACTION_REPLY_TO_ALL,
97         ACTION_FORWARD
98 } ReplyForwardAction;
99
100 typedef struct _ReplyForwardHelper {
101         guint reply_forward_type;
102         ReplyForwardAction action;
103         gchar *account_name;
104         GtkWidget *parent_window;
105 } ReplyForwardHelper;
106
107 typedef struct _MoveToHelper {
108         GtkTreeRowReference *reference;
109         GtkWidget *banner;
110 } MoveToHelper;
111
112 typedef struct _PasteAsAttachmentHelper {
113         ModestMsgEditWindow *window;
114         GtkWidget *banner;
115 } PasteAsAttachmentHelper;
116
117
118 /*
119  * The do_headers_action uses this kind of functions to perform some
120  * action to each member of a list of headers
121  */
122 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
123
124 static void     do_headers_action     (ModestWindow *win, 
125                                        HeadersFunc func,
126                                        gpointer user_data);
127
128 static void     open_msg_cb            (ModestMailOperation *mail_op, 
129                                         TnyHeader *header, 
130                                         gboolean canceled,
131                                         TnyMsg *msg,
132                                         GError *err,
133                                         gpointer user_data);
134
135 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
136                                         TnyHeader *header, 
137                                         gboolean canceled,
138                                         TnyMsg *msg,
139                                         GError *err,
140                                         gpointer user_data);
141
142 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
143
144 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
145                                         TnyFolder *folder, 
146                                         gpointer user_data);
147
148 static void     on_send_receive_finished (ModestMailOperation  *mail_op, 
149                                           gpointer user_data);
150
151 static gint header_list_count_uncached_msgs (TnyList *header_list);
152
153 static gboolean connect_to_get_msg (ModestWindow *win,
154                                     gint num_of_uncached_msgs,
155                                     TnyAccount *account);
156
157 static gboolean remote_folder_is_pop (const TnyFolderStore *folder);
158
159 static gboolean msgs_already_deleted_from_server ( TnyList *headers,
160                                                    const TnyFolderStore *src_folder);
161
162 static void     do_create_folder (GtkWindow *window, 
163                                   TnyFolderStore *parent_folder, 
164                                   const gchar *suggested_name);
165
166 static GtkWidget* get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog);
167
168
169 /*
170  * This function checks whether a TnyFolderStore is a pop account
171  */
172 static gboolean
173 remote_folder_is_pop (const TnyFolderStore *folder)
174 {
175         const gchar *proto = NULL;
176         TnyAccount *account = NULL;
177
178         g_return_val_if_fail (TNY_IS_FOLDER_STORE(folder), FALSE);
179
180         if (TNY_IS_ACCOUNT (folder)) {
181                 account = TNY_ACCOUNT(folder);
182                 g_object_ref(account);
183         } else if (TNY_IS_FOLDER (folder)) {
184                 account = tny_folder_get_account(TNY_FOLDER(folder));
185         }
186
187         if (!account && !TNY_IS_ACCOUNT(account)) {
188                 g_warning ("%s: could not get account", __FUNCTION__);
189                 return FALSE;
190         }
191         
192         proto = tny_account_get_proto(account);
193         g_object_unref (account);
194
195         return proto &&
196           (modest_protocol_info_get_transport_store_protocol (proto) == MODEST_PROTOCOL_STORE_POP);
197 }
198
199 /*
200  * This functions checks whether if a list of messages are already
201  * deleted from the server: that is, if the server is a POP account
202  * and all messages are already cached.
203  */
204 static gboolean
205 msgs_already_deleted_from_server (TnyList *headers, const TnyFolderStore *src_folder)
206 {
207         g_return_val_if_fail (TNY_IS_FOLDER_STORE(src_folder), FALSE);
208         g_return_val_if_fail (TNY_IS_LIST(headers), FALSE);
209
210         gboolean src_is_pop = remote_folder_is_pop (src_folder);
211         gint uncached_msgs = header_list_count_uncached_msgs (headers);
212
213         return (src_is_pop && !uncached_msgs);
214 }
215
216
217 /* FIXME: this should be merged with the similar code in modest-account-view-window */
218 /* Show the account creation wizard dialog.
219  * returns: TRUE if an account was created. FALSE if the user cancelled.
220  */
221 gboolean
222 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
223 {
224         gboolean result = FALSE;        
225         GtkWindow *dialog, *wizard;
226         gint dialog_response;
227
228         /* Show the easy-setup wizard: */       
229         dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr());
230         if (dialog) {
231                 /* old wizard is active already; 
232                  */
233                 gtk_window_present (GTK_WINDOW(dialog));
234                 return FALSE;
235         }
236         
237
238         /* there is no such wizard yet */       
239         wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
240         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), wizard);
241
242         /* always present a main window in the background 
243          * we do it here, so we cannot end up with two wizards (as this
244          * function might be called in modest_window_mgr_get_main_window as well */
245         if (!win) 
246                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
247                                                          TRUE);  /* create if not existent */
248         
249         /* make sure the mainwindow is visible */
250         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
251         gtk_widget_show_all (GTK_WIDGET(win));
252         gtk_window_present (GTK_WINDOW(win));
253         
254         dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
255         gtk_widget_destroy (GTK_WIDGET (wizard));
256         if (gtk_events_pending ())
257                 gtk_main_iteration ();
258
259         if (dialog_response == GTK_RESPONSE_CANCEL) {
260                 result = FALSE;
261         } else {
262                 /* Check whether an account was created: */
263                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
264         }
265         return result;
266 }
267
268
269 void   
270 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
271 {
272         GtkWidget *about;
273         const gchar *authors[] = {
274                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
275                 NULL
276         };
277         about = gtk_about_dialog_new ();
278         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
279         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
280         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
281                                         _("Copyright (c) 2006, Nokia Corporation\n"
282                                           "All rights reserved."));
283         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
284                                        _("a modest e-mail client\n\n"
285                                          "design and implementation: Dirk-Jan C. Binnema\n"
286                                          "contributions from the fine people at KC and Ig\n"
287                                          "uses the tinymail email framework written by Philip van Hoof"));
288         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
289         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
290         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
291         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
292         
293         gtk_dialog_run (GTK_DIALOG (about));
294         gtk_widget_destroy(about);
295 }
296
297 /*
298  * Gets the list of currently selected messages. If the win is the
299  * main window, then it returns a newly allocated list of the headers
300  * selected in the header view. If win is the msg view window, then
301  * the value returned is a list with just a single header.
302  *
303  * The caller of this funcion must free the list.
304  */
305 static TnyList *
306 get_selected_headers (ModestWindow *win)
307 {
308         if (MODEST_IS_MAIN_WINDOW(win)) {
309                 GtkWidget *header_view;         
310                 
311                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
312                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
313                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
314                 
315         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
316                 /* for MsgViewWindows, we simply return a list with one element */
317                 TnyHeader *header;
318                 TnyList *list = NULL;
319                 
320                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
321                 if (header != NULL) {
322                         list = tny_simple_list_new ();
323                         tny_list_prepend (list, G_OBJECT(header));
324                         g_object_unref (G_OBJECT(header));
325                 }
326
327                 return list;
328
329         } else
330                 return NULL;
331 }
332
333 static GtkTreeRowReference *
334 get_next_after_selected_headers (ModestHeaderView *header_view)
335 {
336         GtkTreeSelection *sel;
337         GList *selected_rows, *node;
338         GtkTreePath *path;
339         GtkTreeRowReference *result;
340         GtkTreeModel *model;
341
342         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
343         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
344         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
345
346         if (selected_rows == NULL)
347                 return NULL;
348
349         node = g_list_last (selected_rows);
350         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
351         gtk_tree_path_next (path);
352
353         result = gtk_tree_row_reference_new (model, path);
354
355         gtk_tree_path_free (path);
356         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
357         g_list_free (selected_rows);
358
359         return result;
360 }
361
362 static void
363 headers_action_mark_as_read (TnyHeader *header,
364                              ModestWindow *win,
365                              gpointer user_data)
366 {
367         TnyHeaderFlags flags;
368
369         g_return_if_fail (TNY_IS_HEADER(header));
370
371         flags = tny_header_get_flags (header);
372         if (flags & TNY_HEADER_FLAG_SEEN) return;
373         tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
374 }
375
376 static void
377 headers_action_mark_as_unread (TnyHeader *header,
378                                ModestWindow *win,
379                                gpointer user_data)
380 {
381         TnyHeaderFlags flags;
382
383         g_return_if_fail (TNY_IS_HEADER(header));
384
385         flags = tny_header_get_flags (header);
386         if (flags & TNY_HEADER_FLAG_SEEN)  {
387                 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
388         }
389 }
390
391 /** After deleing a message that is currently visible in a window, 
392  * show the next message from the list, or close the window if there are no more messages.
393  **/
394 void 
395 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
396 {
397         /* Close msg view window or select next */
398         if (modest_msg_view_window_last_message_selected (win) &&
399                 modest_msg_view_window_first_message_selected (win)) {
400                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
401         } else if (!modest_msg_view_window_select_next_message (win)) {
402                 gboolean ret_value;
403                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);       
404         }
405 }
406
407
408 void
409 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
410 {
411         TnyList *header_list = NULL;
412         TnyIterator *iter = NULL;
413         TnyHeader *header = NULL;
414         gchar *message = NULL;
415         gchar *desc = NULL;
416         gint response;
417         ModestWindowMgr *mgr;
418         GtkWidget *header_view = NULL;
419
420         g_return_if_fail (MODEST_IS_WINDOW(win));
421         
422         /* Check first if the header view has the focus */
423         if (MODEST_IS_MAIN_WINDOW (win)) {
424                 header_view = 
425                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
426                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
427                 if (!gtk_widget_is_focus (header_view))
428                         return;
429         }
430         
431         /* Get the headers, either from the header view (if win is the main window),
432          * or from the message view window: */
433         header_list = get_selected_headers (win);
434         if (!header_list) return;
435                         
436         /* Check if any of the headers are already opened, or in the process of being opened */
437         if (MODEST_IS_MAIN_WINDOW (win)) {
438                 gint opened_headers = 0;
439
440                 iter = tny_list_create_iterator (header_list);
441                 mgr = modest_runtime_get_window_mgr ();
442                 while (!tny_iterator_is_done (iter)) {
443                         header = TNY_HEADER (tny_iterator_get_current (iter));
444                         if (header) {
445                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
446                                         opened_headers++;
447                                 g_object_unref (header);
448                         }
449                         tny_iterator_next (iter);
450                 }
451                 g_object_unref (iter);
452
453                 if (opened_headers > 0) {
454                         gchar *msg;
455
456                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), 
457                                                opened_headers);
458
459                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
460                         
461                         g_free (msg);
462                         g_object_unref (header_list);
463                         return;
464                 }
465         }
466
467         /* Select message */
468         if (tny_list_get_length(header_list) == 1) {
469                 iter = tny_list_create_iterator (header_list);
470                 header = TNY_HEADER (tny_iterator_get_current (iter));
471                 if (header) {
472                         desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
473                         g_object_unref (header);
474                 }
475
476                 g_object_unref (iter);
477         }
478         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
479                                            tny_list_get_length(header_list)), desc);
480
481         /* Confirmation dialog */
482         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
483                                                             message);
484         
485
486         if (response == GTK_RESPONSE_OK) {      
487                 ModestWindow *main_window = NULL;
488                 ModestWindowMgr *mgr = NULL;
489                 GtkTreeModel *model = NULL;
490                 GtkTreeSelection *sel = NULL;
491                 GList *sel_list = NULL, *tmp = NULL;
492                 GtkTreeRowReference *next_row_reference = NULL;
493                 GtkTreeRowReference *prev_row_reference = NULL;
494                 GtkTreePath *next_path = NULL;
495                 GtkTreePath *prev_path = NULL;
496                 ModestMailOperation *mail_op = NULL;
497
498                 /* Find last selected row */                    
499                 if (MODEST_IS_MAIN_WINDOW (win)) {
500                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
501                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
502                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
503                         for (tmp=sel_list; tmp; tmp=tmp->next) {
504                                 if (tmp->next == NULL) {
505                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
506                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
507
508                                         gtk_tree_path_prev (prev_path);
509                                         gtk_tree_path_next (next_path);
510
511                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
512                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
513                                 }
514                         }
515                 }
516                 
517                 /* Disable window dimming management */
518                 modest_window_disable_dimming (MODEST_WINDOW(win));
519
520                 /* Remove each header. If it's a view window header_view == NULL */
521                 mail_op = modest_mail_operation_new ((GObject *) win);
522                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
523                                                  mail_op);
524                 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
525                 g_object_unref (mail_op);
526                 
527                 /* Enable window dimming management */
528                 if (sel != NULL) {
529                         gtk_tree_selection_unselect_all (sel);
530                 }
531                 modest_window_enable_dimming (MODEST_WINDOW(win));
532                 
533                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
534                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
535                         
536                         /* Get main window */
537                         mgr = modest_runtime_get_window_mgr ();
538                         main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
539                 } else {                        
540                         /* Move cursor to next row */
541                         main_window = win; 
542
543                         /* Select next or previous row */
544                         if (gtk_tree_row_reference_valid (next_row_reference)) {
545 /*                              next_path = gtk_tree_row_reference_get_path (row_reference); */
546                                 gtk_tree_selection_select_path (sel, next_path);
547                         }
548                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {                           
549                                 gtk_tree_selection_select_path (sel, prev_path);
550                         }
551
552                         /* Free */
553                         if (next_row_reference != NULL) 
554                                 gtk_tree_row_reference_free (next_row_reference);
555                         if (next_path != NULL) 
556                                 gtk_tree_path_free (next_path);                         
557                         if (prev_row_reference != NULL) 
558                                 gtk_tree_row_reference_free (prev_row_reference);
559                         if (prev_path != NULL) 
560                                 gtk_tree_path_free (prev_path);                         
561                 }
562                 
563                 /* Update toolbar dimming state */
564                 if (main_window)
565                         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
566
567                 /* Free */
568                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
569                 g_list_free (sel_list);
570         }
571
572         /* Free*/
573         g_free(message);
574         g_free(desc);
575         g_object_unref (header_list);
576 }
577
578
579
580
581 /* delete either message or folder, based on where we are */
582 void
583 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
584 {
585         g_return_if_fail (MODEST_IS_WINDOW(win));
586         
587         /* Check first if the header view has the focus */
588         if (MODEST_IS_MAIN_WINDOW (win)) {
589                 GtkWidget *w;
590                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
591                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
592                 if (gtk_widget_is_focus (w)) {
593                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
594                         return;
595                 }
596         }
597         modest_ui_actions_on_delete_message (action, win);
598 }
599
600
601
602 void
603 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
604 {       
605         ModestWindowMgr *mgr = NULL;
606         
607 #ifdef MODEST_PLATFORM_MAEMO
608         modest_osso_save_state();
609 #endif /* MODEST_PLATFORM_MAEMO */
610
611         g_debug ("closing down, clearing %d item(s) from operation queue",
612                  modest_mail_operation_queue_num_elements
613                  (modest_runtime_get_mail_operation_queue()));
614
615         /* cancel all outstanding operations */
616         modest_mail_operation_queue_cancel_all 
617                 (modest_runtime_get_mail_operation_queue());
618         
619         g_debug ("queue has been cleared");
620
621
622         /* Check if there are opened editing windows */ 
623         mgr = modest_runtime_get_window_mgr ();
624         modest_window_mgr_close_all_windows (mgr);
625
626         /* note: when modest-tny-account-store is finalized,
627            it will automatically set all network connections
628            to offline */
629
630 /*      gtk_main_quit (); */
631 }
632
633 void
634 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
635 {
636         gboolean ret_value;
637
638         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
639
640 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
641 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
642 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
643 /*              gboolean ret_value; */
644 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
645 /*      } else if (MODEST_IS_WINDOW (win)) { */
646 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
647 /*      } else { */
648 /*              g_return_if_reached (); */
649 /*      } */
650 }
651
652 void
653 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
654 {
655         GtkClipboard *clipboard = NULL;
656         gchar *selection = NULL;
657
658         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
659         selection = gtk_clipboard_wait_for_text (clipboard);
660
661         /* Question: why is the clipboard being used here? 
662          * It doesn't really make a lot of sense. */
663
664         if (selection)
665         {
666                 modest_address_book_add_address (selection);
667                 g_free (selection);
668         }
669 }
670
671 void
672 modest_ui_actions_on_accounts (GtkAction *action, 
673                                ModestWindow *win)
674 {
675         /* This is currently only implemented for Maemo */
676         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
677                 if (!modest_ui_actions_run_account_setup_wizard (win)) 
678                         g_debug ("%s: wizard was already running", __FUNCTION__);
679                 
680                 return;
681         } else {
682                 /* Show the list of accounts */
683                 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
684                 gtk_window_set_transient_for (account_win, GTK_WINDOW (win));
685                 
686                 /* The accounts dialog must be modal */
687                 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), account_win);
688                 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win)); 
689         }
690 }
691
692 #ifdef MODEST_PLATFORM_MAEMO
693 static void
694 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
695 {
696         /* Save any changes. */
697         modest_connection_specific_smtp_window_save_server_accounts (
698                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
699         gtk_widget_destroy (GTK_WIDGET (window));
700 }
701 #endif
702
703
704 void
705 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
706 {
707         /* This is currently only implemented for Maemo,
708          * because it requires an API (libconic) to detect different connection 
709          * possiblities.
710          */
711 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
712         
713         /* Create the window if necessary: */
714         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
715         modest_connection_specific_smtp_window_fill_with_connections (
716                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
717                 modest_runtime_get_account_mgr());
718
719         /* Show the window: */  
720         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
721         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
722         gtk_widget_show (specific_window);
723     
724         /* Save changes when the window is hidden: */
725         g_signal_connect (specific_window, "hide", 
726                 G_CALLBACK (on_smtp_servers_window_hide), win);
727 #endif /* MODEST_PLATFORM_MAEMO */
728 }
729
730 void
731 modest_ui_actions_compose_msg(ModestWindow *win,
732                               const gchar *to_str,
733                               const gchar *cc_str,
734                               const gchar *bcc_str,
735                               const gchar *subject_str,
736                               const gchar *body_str,
737                               GSList *attachments)
738 {
739         gchar *account_name = NULL;
740         TnyMsg *msg = NULL;
741         TnyAccount *account = NULL;
742         TnyFolder *folder = NULL;
743         gchar *from_str = NULL, *signature = NULL, *body = NULL;
744         gboolean use_signature = FALSE;
745         ModestWindow *msg_win = NULL;
746         ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
747         ModestTnyAccountStore *store = modest_runtime_get_account_store();
748
749         account_name = modest_account_mgr_get_default_account(mgr);
750         if (!account_name) {
751                 g_printerr ("modest: no account found\n");
752                 goto cleanup;
753         }
754         account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
755         if (!account) {
756                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
757                 goto cleanup;
758         }
759         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
760         if (!folder) {
761                 g_printerr ("modest: failed to find Drafts folder\n");
762                 goto cleanup;
763         }
764         from_str = modest_account_mgr_get_from_string (mgr, account_name);
765         if (!from_str) {
766                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
767                 goto cleanup;
768         }
769
770         signature = modest_account_mgr_get_signature (mgr, account_name, &use_signature);
771         if (body_str != NULL) {
772                 body = use_signature ? g_strconcat(body_str, "\n", signature, NULL) : g_strdup(body_str);
773         } else {
774                 body = use_signature ? g_strconcat("\n", signature, NULL) : g_strdup("");
775         }
776
777         msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, body, NULL);
778         if (!msg) {
779                 g_printerr ("modest: failed to create new msg\n");
780                 goto cleanup;
781         }
782
783         /* Create and register edit window */
784         /* This is destroyed by TODO. */
785         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
786         while (attachments) {
787                 modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
788                                                        attachments->data);
789                 attachments = g_slist_next(attachments);
790         }
791         modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win);
792         gtk_widget_show_all (GTK_WIDGET (msg_win));
793
794 cleanup:
795         g_free (from_str);
796         g_free (signature);
797         g_free (body);
798         g_free (account_name);
799         if (account) g_object_unref (G_OBJECT(account));
800         if (folder) g_object_unref (G_OBJECT(folder));
801         if (msg_win) g_object_unref (G_OBJECT(msg_win));
802         if (msg) g_object_unref (G_OBJECT(msg));
803 }
804
805 void
806 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
807 {
808         /* if there are no accounts yet, just show the wizard */
809         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
810                 if (!modest_ui_actions_run_account_setup_wizard (win))
811                         return;
812                 
813         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL);
814 }
815
816 void
817 modest_ui_actions_on_new_msg_or_folder (GtkAction *action, ModestWindow *win)
818 {
819         g_return_if_fail (MODEST_IS_WINDOW (win));
820
821         /* Check first if the folder view has the focus */
822         if (MODEST_IS_MAIN_WINDOW (win)) {
823                 GtkWidget *w;
824                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
825                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
826                 if (gtk_widget_is_focus (w)) {
827                         modest_ui_actions_on_new_folder (action, MODEST_MAIN_WINDOW(win));
828                         return;
829                 }
830         }
831
832         modest_ui_actions_on_new_msg (action, win);
833 }
834
835
836 gboolean 
837 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
838                                        TnyHeader *header,
839                                        TnyMsg *msg)
840 {
841         ModestMailOperationStatus status;
842
843         /* If there is no message or the operation was not successful */
844         status = modest_mail_operation_get_status (mail_op);
845         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
846
847                 /* Remove the header from the preregistered uids */
848                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
849                                                      header);
850
851                 return FALSE;
852         }
853
854         return TRUE;
855 }
856
857 static void
858 open_msg_cb (ModestMailOperation *mail_op, 
859              TnyHeader *header,  
860              gboolean canceled,
861              TnyMsg *msg, 
862              GError *err,
863              gpointer user_data)
864 {
865         ModestWindowMgr *mgr = NULL;
866         ModestWindow *parent_win = NULL;
867         ModestWindow *win = NULL;
868         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
869         gchar *account = NULL;
870         TnyFolder *folder;
871         gboolean open_in_editor = FALSE;
872         
873         /* Do nothing if there was any problem with the mail
874            operation. The error will be shown by the error_handler of
875            the mail operation */
876         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
877                 return;
878
879         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
880         folder = tny_header_get_folder (header);
881
882         /* Mark header as read */
883         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
884
885         /* Gets folder type (OUTBOX headers will be opened in edit window */
886         if (modest_tny_folder_is_local_folder (folder)) {
887                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
888                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
889                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
890         }
891
892                 
893         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
894                 TnyTransportAccount *traccount = NULL;
895                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
896                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
897                 if (traccount) {
898                         ModestTnySendQueue *send_queue = NULL;
899                         ModestTnySendQueueStatus status;
900                         char *msg_id;
901                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
902                                                    TNY_ACCOUNT(traccount)));
903                         send_queue = modest_runtime_get_send_queue(traccount);
904                         msg_id = modest_tny_send_queue_get_msg_id (header);
905                         status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
906                         /* Only open messages in outbox with the editor if they are in Failed state */
907                         if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
908                                 open_in_editor = TRUE;
909                         }
910                         g_free(msg_id);
911                         g_object_unref(traccount);
912                 } else {
913                         g_warning("Cannot get transport account for message in outbox!!");
914                 }
915         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
916                 open_in_editor = TRUE; /* Open in editor if the message is in the Drafts folder */
917         }
918
919         /* Get account */
920         if (!account)
921                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
922         if (!account)
923                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
924         
925         if (open_in_editor) {
926                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
927                 const gchar *from_header = NULL;
928
929                 from_header = tny_header_get_from (header);
930
931                 /* we cannot edit without a valid account... */
932                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
933                         if (!modest_ui_actions_run_account_setup_wizard(parent_win))
934                                 goto cleanup;
935                 }
936                 
937                 if (from_header) {
938                         GSList *accounts = modest_account_mgr_account_names (mgr, TRUE);
939                         GSList *node = NULL;
940                         for (node = accounts; node != NULL; node = g_slist_next (node)) {
941                                 gchar *from = modest_account_mgr_get_from_string (mgr, node->data);
942                                 
943                                 if (from && (strcmp (from_header, from) == 0)) {
944                                         g_free (account);
945                                         account = g_strdup (node->data);
946                                         g_free (from);
947                                         break;
948                                 }
949                                 g_free (from);
950                         }
951                         g_slist_foreach (accounts, (GFunc) g_free, NULL);
952                         g_slist_free (accounts);
953                 }
954
955                 win = modest_msg_edit_window_new (msg, account, TRUE);
956
957
958                 /* Show banner */
959                 modest_platform_information_banner_with_timeout
960                         (NULL, NULL, _("mail_ib_opening_draft_message"), 1200);
961
962         } else {
963                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
964                 
965                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
966                         GtkWidget *header_view;
967                         GtkTreeSelection *sel;
968                         GList *sel_list = NULL;
969                         GtkTreeModel *model;
970                         
971                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
972                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
973
974                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
975                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
976
977                         if (sel_list != NULL) {
978                                 GtkTreeRowReference *row_reference;
979
980                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
981                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
982                                 g_list_free (sel_list);
983                                 
984                                 win = modest_msg_view_window_new_with_header_model (
985                                                 msg, account, (const gchar*) uid,
986                                                 model, row_reference);
987                                 gtk_tree_row_reference_free (row_reference);
988                         } else {
989                                 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
990                         }
991                 } else {
992                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
993                 }
994                 g_free (uid);
995         }
996         
997         /* Register and show new window */
998         if (win != NULL) {
999                 mgr = modest_runtime_get_window_mgr ();
1000                 modest_window_mgr_register_window (mgr, win);
1001                 g_object_unref (win);
1002                 gtk_widget_show_all (GTK_WIDGET(win));
1003         }
1004
1005         /* Update toolbar dimming state */
1006         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
1007                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1008         }
1009
1010 cleanup:
1011         /* Free */
1012         g_free(account);
1013         g_object_unref (parent_win);
1014         g_object_unref (folder);
1015 }
1016
1017 void
1018 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
1019                                                gpointer user_data)
1020 {
1021         const GError *error;
1022         GObject *win = NULL;
1023         const gchar *err_msg;
1024
1025         win = modest_mail_operation_get_source (mail_op);
1026         error = modest_mail_operation_get_error (mail_op);
1027  
1028         /* Select error message */
1029         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT)
1030                 err_msg = _("emev_ni_ui_imap_msg_size_exceed_error");
1031         else
1032                 err_msg = (const gchar *) user_data;
1033
1034         /* Show error */
1035         modest_platform_run_information_dialog ((GtkWindow *) win, err_msg);
1036
1037         if (win)
1038                 g_object_unref (win);
1039 }
1040
1041 /**
1042  * Returns the account a list of headers belongs to. It returns a
1043  * *new* reference so don't forget to unref it
1044  */
1045 static TnyAccount*
1046 get_account_from_header_list (TnyList *headers)
1047 {
1048         TnyAccount *account = NULL;
1049
1050         if (tny_list_get_length (headers) > 0) {
1051                 TnyIterator *iter = tny_list_create_iterator (headers);
1052                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1053                 TnyFolder *folder = tny_header_get_folder (header);
1054                 account = tny_folder_get_account (folder);
1055                 g_object_unref (folder);
1056                 g_object_unref (header);
1057                 g_object_unref (iter);
1058         }
1059         return account;
1060 }
1061
1062 static void 
1063 foreach_unregister_headers (gpointer data,
1064                             gpointer user_data)
1065 {
1066         ModestWindowMgr *mgr = (ModestWindowMgr *) user_data;
1067         TnyHeader *header = TNY_HEADER (data);
1068
1069         modest_window_mgr_unregister_header (mgr, header);
1070 }
1071
1072 static void
1073 open_msgs_performer(gboolean canceled, 
1074                     GError *err,
1075                     GtkWindow *parent_window,
1076                     TnyAccount *account,
1077                     gpointer user_data)
1078 {
1079         ModestMailOperation *mail_op = NULL;
1080         const gchar *proto_name;
1081         gchar *error_msg;
1082         ModestTransportStoreProtocol proto;
1083         TnyList *not_opened_headers;
1084         TnyConnectionStatus status;
1085
1086         not_opened_headers = TNY_LIST (user_data);
1087
1088         status = tny_account_get_connection_status (account);
1089         if (err || canceled) {
1090                 /* Unregister the already registered headers */
1091                 tny_list_foreach (not_opened_headers, foreach_unregister_headers, 
1092                                   modest_runtime_get_window_mgr ());
1093                 goto clean;
1094         }
1095
1096         /* Get the error message depending on the protocol */
1097         proto_name = tny_account_get_proto (account);
1098         if (proto_name != NULL) {
1099                 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
1100         } else {
1101                 proto = MODEST_PROTOCOL_STORE_MAILDIR;
1102         }
1103         
1104         /* Create the error messages */
1105         if (tny_list_get_length (not_opened_headers) == 1) {
1106                 if (proto == MODEST_PROTOCOL_STORE_POP) {
1107                         error_msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
1108                 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
1109                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1110                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1111                         error_msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
1112                                                      tny_header_get_subject (header));
1113                         g_object_unref (header);
1114                         g_object_unref (iter);
1115                 } else {
1116                         error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1117                 }
1118         } else {
1119                 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1120         }
1121
1122         /* Create the mail operation */
1123         mail_op = 
1124                 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1125                                                                modest_ui_actions_get_msgs_full_error_handler,
1126                                                                error_msg, g_free);
1127         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1128                                          mail_op);
1129                 
1130         modest_mail_operation_get_msgs_full (mail_op,
1131                                              not_opened_headers,
1132                                              open_msg_cb,
1133                                              NULL,
1134                                              NULL);
1135
1136         /* Frees */
1137  clean:
1138         if (mail_op)
1139                 g_object_unref (mail_op);
1140         g_object_unref (not_opened_headers);
1141         g_object_unref (account);
1142 }
1143
1144 /*
1145  * This function is used by both modest_ui_actions_on_open and
1146  * modest_ui_actions_on_header_activated. This way we always do the
1147  * same when trying to open messages.
1148  */
1149 static void
1150 open_msgs_from_headers (TnyList *headers, ModestWindow *win)
1151 {
1152         ModestWindowMgr *mgr = NULL;
1153         TnyIterator *iter = NULL, *iter_not_opened = NULL;
1154         TnyList *not_opened_headers = NULL;
1155         TnyHeaderFlags flags = 0;
1156         TnyAccount *account;
1157         gint uncached_msgs = 0;
1158                 
1159         g_return_if_fail (headers != NULL);
1160
1161         /* Check that only one message is selected for opening */
1162         if (tny_list_get_length (headers) != 1) {
1163                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1164                                                         _("mcen_ib_select_one_message"));
1165                 return;
1166         }
1167
1168         mgr = modest_runtime_get_window_mgr ();
1169         iter = tny_list_create_iterator (headers);
1170
1171         /* Get the account */
1172         account = get_account_from_header_list (headers);
1173         
1174         /* Look if we already have a message view for each header. If
1175            true, then remove the header from the list of headers to
1176            open */
1177         not_opened_headers = tny_simple_list_new ();
1178         while (!tny_iterator_is_done (iter)) {
1179
1180                 ModestWindow *window = NULL;
1181                 TnyHeader *header = NULL;
1182                 gboolean found = FALSE;
1183                 
1184                 header = TNY_HEADER (tny_iterator_get_current (iter));
1185                 if (header)
1186                         flags = tny_header_get_flags (header);
1187
1188                 window = NULL;
1189                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1190                 
1191                 /* Do not open again the message and present the
1192                    window to the user */
1193                 if (found) {
1194                         if (window)
1195                                 gtk_window_present (GTK_WINDOW (window));
1196                         else
1197                                 /* the header has been registered already, we don't do
1198                                  * anything but wait for the window to come up*/
1199                                 g_debug ("header %p already registered, waiting for window", header);
1200                 } else {
1201                         tny_list_append (not_opened_headers, G_OBJECT (header));
1202                 }
1203
1204                 if (header)
1205                         g_object_unref (header);
1206
1207                 tny_iterator_next (iter);
1208         }
1209         g_object_unref (iter);
1210         iter = NULL;
1211
1212         /* Open each message */
1213         if (tny_list_get_length (not_opened_headers) == 0)
1214                 goto cleanup;
1215         
1216         /* If some messages would have to be downloaded, ask the user to 
1217          * make a connection. It's generally easier to do this here (in the mainloop) 
1218          * than later in a thread:
1219          */
1220         if (tny_list_get_length (not_opened_headers) > 0) {
1221                 uncached_msgs = header_list_count_uncached_msgs (not_opened_headers);
1222
1223                 if (uncached_msgs > 0) {
1224                         /* Allways download if we are online. */
1225                         if (!tny_device_is_online (modest_runtime_get_device ())) {
1226                                 gint response;
1227
1228                                 /* If ask for user permission to download the messages */
1229                                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1230                                                                                     ngettext("mcen_nc_get_msg",
1231                                                                                              "mcen_nc_get_msgs",
1232                                                                                              uncached_msgs));
1233
1234                                 /* End if the user does not want to continue */
1235                                 if (response == GTK_RESPONSE_CANCEL)
1236                                         goto cleanup;
1237                         }
1238                 }
1239         }
1240         
1241         /* Register the headers before actually creating the windows: */
1242         iter_not_opened = tny_list_create_iterator (not_opened_headers);
1243         while (!tny_iterator_is_done (iter_not_opened)) {
1244                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1245                 if (header) {
1246                         modest_window_mgr_register_header (mgr, header, NULL);
1247                         g_object_unref (header);
1248                 }
1249                 tny_iterator_next (iter_not_opened);
1250         }
1251         g_object_unref (iter_not_opened);
1252         iter_not_opened = NULL;
1253
1254         /* Connect to the account and perform */
1255         if (uncached_msgs > 0) {
1256                 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account), 
1257                                                      open_msgs_performer, g_object_ref (not_opened_headers));
1258         } else {
1259                 /* Call directly the performer, do not need to connect */
1260                 open_msgs_performer (FALSE, NULL, (GtkWindow *) win, g_object_ref (account),
1261                                      g_object_ref (not_opened_headers));
1262         }
1263 cleanup:
1264         /* Clean */
1265         if (account)
1266                 g_object_unref (account);
1267         if (not_opened_headers)
1268                 g_object_unref (not_opened_headers);
1269 }
1270
1271 void
1272 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1273 {
1274         TnyList *headers;
1275
1276         /* Get headers */
1277         headers = get_selected_headers (win);
1278         if (!headers)
1279                 return;
1280
1281         /* Open them */
1282         open_msgs_from_headers (headers, win);
1283
1284         g_object_unref(headers);
1285 }
1286
1287
1288 static void
1289 free_reply_forward_helper (gpointer data)
1290 {
1291         ReplyForwardHelper *helper;
1292
1293         helper = (ReplyForwardHelper *) data;
1294         g_free (helper->account_name);
1295         g_slice_free (ReplyForwardHelper, helper);
1296 }
1297
1298 static void
1299 reply_forward_cb (ModestMailOperation *mail_op,  
1300                   TnyHeader *header, 
1301                   gboolean canceled,
1302                   TnyMsg *msg,
1303                   GError *err,
1304                   gpointer user_data)
1305 {
1306         TnyMsg *new_msg;
1307         ReplyForwardHelper *rf_helper;
1308         ModestWindow *msg_win = NULL;
1309         ModestEditType edit_type;
1310         gchar *from = NULL;
1311         TnyAccount *account = NULL;
1312         ModestWindowMgr *mgr = NULL;
1313         gchar *signature = NULL;
1314         gboolean use_signature;
1315
1316         /* If there was any error. The mail operation could be NULL,
1317            this means that we already have the message downloaded and
1318            that we didn't do a mail operation to retrieve it */
1319         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1320                 return;
1321                         
1322         g_return_if_fail (user_data != NULL);
1323         rf_helper = (ReplyForwardHelper *) user_data;
1324
1325         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1326                                                    rf_helper->account_name);
1327         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(), 
1328                                                       rf_helper->account_name, 
1329                                                       &use_signature);
1330
1331         /* Create reply mail */
1332         switch (rf_helper->action) {
1333         case ACTION_REPLY:
1334                 new_msg = 
1335                         modest_tny_msg_create_reply_msg (msg, header, from, signature,
1336                                                          rf_helper->reply_forward_type,
1337                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1338                 break;
1339         case ACTION_REPLY_TO_ALL:
1340                 new_msg = 
1341                         modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1342                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1343                 edit_type = MODEST_EDIT_TYPE_REPLY;
1344                 break;
1345         case ACTION_FORWARD:
1346                 new_msg = 
1347                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1348                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1349                 break;
1350         default:
1351                 g_return_if_reached ();
1352                 return;
1353         }
1354
1355         g_free (signature);
1356
1357         if (!new_msg) {
1358                 g_printerr ("modest: failed to create message\n");
1359                 goto cleanup;
1360         }
1361
1362         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1363                                                                        rf_helper->account_name,
1364                                                                        TNY_ACCOUNT_TYPE_STORE);
1365         if (!account) {
1366                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1367                 goto cleanup;
1368         }
1369
1370         /* Create and register the windows */
1371         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1372         mgr = modest_runtime_get_window_mgr ();
1373         modest_window_mgr_register_window (mgr, msg_win);
1374
1375         if (rf_helper->parent_window != NULL) {
1376                 gdouble parent_zoom;
1377
1378                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1379                 modest_window_set_zoom (msg_win, parent_zoom);
1380         }
1381
1382         /* Show edit window */
1383         gtk_widget_show_all (GTK_WIDGET (msg_win));
1384
1385 cleanup:
1386         if (msg_win)
1387                 g_object_unref (msg_win);
1388         if (new_msg)
1389                 g_object_unref (G_OBJECT (new_msg));
1390         if (account)
1391                 g_object_unref (G_OBJECT (account));
1392 /*      g_object_unref (msg); */
1393         free_reply_forward_helper (rf_helper);
1394 }
1395
1396 /* Checks a list of headers. If any of them are not currently
1397  * downloaded (CACHED) then returns TRUE else returns FALSE.
1398  */
1399 static gint
1400 header_list_count_uncached_msgs (TnyList *header_list)
1401 {
1402         TnyIterator *iter;
1403         gint uncached_messages = 0;
1404
1405         iter = tny_list_create_iterator (header_list);
1406         while (!tny_iterator_is_done (iter)) {
1407                 TnyHeader *header;
1408
1409                 header = TNY_HEADER (tny_iterator_get_current (iter));
1410                 if (header) {
1411                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1412                                 uncached_messages ++;
1413                         g_object_unref (header);
1414                 }
1415
1416                 tny_iterator_next (iter);
1417         }
1418         g_object_unref (iter);
1419
1420         return uncached_messages;
1421 }
1422
1423 /* Returns FALSE if the user does not want to download the
1424  * messages. Returns TRUE if the user allowed the download.
1425  */
1426 static gboolean
1427 connect_to_get_msg (ModestWindow *win,
1428                     gint num_of_uncached_msgs,
1429                     TnyAccount *account)
1430 {
1431         GtkResponseType response;
1432
1433         /* Allways download if we are online. */
1434         if (tny_device_is_online (modest_runtime_get_device ()))
1435                 return TRUE;
1436
1437         /* If offline, then ask for user permission to download the messages */
1438         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1439                         ngettext("mcen_nc_get_msg",
1440                         "mcen_nc_get_msgs",
1441                         num_of_uncached_msgs));
1442
1443         if (response == GTK_RESPONSE_CANCEL)
1444                 return FALSE;
1445
1446         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1447 }
1448
1449 /*
1450  * Common code for the reply and forward actions
1451  */
1452 static void
1453 reply_forward (ReplyForwardAction action, ModestWindow *win)
1454 {
1455         ModestMailOperation *mail_op = NULL;
1456         TnyList *header_list = NULL;
1457         ReplyForwardHelper *rf_helper = NULL;
1458         guint reply_forward_type;
1459         gboolean continue_download = TRUE;
1460         gboolean do_retrieve = TRUE;
1461         
1462         g_return_if_fail (MODEST_IS_WINDOW(win));
1463
1464         /* we need an account when editing */
1465         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1466                 if (!modest_ui_actions_run_account_setup_wizard (win))
1467                         return;
1468         }
1469         
1470         header_list = get_selected_headers (win);
1471         if (!header_list)
1472                 return;
1473
1474         reply_forward_type = 
1475                 modest_conf_get_int (modest_runtime_get_conf (),
1476                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1477                                      NULL);
1478
1479         /* check if we need to download msg before asking about it */
1480         do_retrieve = (action == ACTION_FORWARD) ||
1481                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1482
1483         if (do_retrieve){
1484                 gint num_of_unc_msgs;
1485
1486                 /* check that the messages have been previously downloaded */
1487                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1488                 /* If there are any uncached message ask the user
1489                  * whether he/she wants to download them. */
1490                 if (num_of_unc_msgs) {
1491                         TnyAccount *account = get_account_from_header_list (header_list);
1492                         continue_download = connect_to_get_msg (win, num_of_unc_msgs, account);
1493                         g_object_unref (account);
1494                 }
1495         }
1496
1497         if (!continue_download) {
1498                 g_object_unref (header_list);
1499                 return;
1500         }
1501         
1502         /* We assume that we can only select messages of the
1503            same folder and that we reply all of them from the
1504            same account. In fact the interface currently only
1505            allows single selection */
1506         
1507         /* Fill helpers */
1508         rf_helper = g_slice_new0 (ReplyForwardHelper);
1509         rf_helper->reply_forward_type = reply_forward_type;
1510         rf_helper->action = action;
1511         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1512         
1513         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1514                 rf_helper->parent_window = GTK_WIDGET (win);
1515         if (!rf_helper->account_name)
1516                 rf_helper->account_name =
1517                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1518
1519         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1520                 TnyMsg *msg;
1521                 TnyHeader *header;
1522                 /* Get header and message. Do not free them here, the
1523                    reply_forward_cb must do it */
1524                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1525                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1526                 if (!msg || !header) {
1527                         if (msg)
1528                                 g_object_unref (msg);
1529                         g_printerr ("modest: no message found\n");
1530                         return;
1531                 } else {
1532                         reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1533                 }
1534                 if (header)
1535                         g_object_unref (header);
1536         } else {
1537                 TnyHeader *header;
1538                 TnyIterator *iter;
1539
1540                 /* Only reply/forward to one message */
1541                 iter = tny_list_create_iterator (header_list);
1542                 header = TNY_HEADER (tny_iterator_get_current (iter));
1543                 g_object_unref (iter);
1544
1545                 if (header) {
1546                         /* Retrieve messages */
1547                         if (do_retrieve) {
1548                                 mail_op = 
1549                                         modest_mail_operation_new_with_error_handling (G_OBJECT(win),
1550                                                                                        modest_ui_actions_get_msgs_full_error_handler, 
1551                                                                                        NULL, NULL);
1552                                 modest_mail_operation_queue_add (
1553                                         modest_runtime_get_mail_operation_queue (), mail_op);
1554                                 
1555                                 modest_mail_operation_get_msg (mail_op,
1556                                                                header,
1557                                                                reply_forward_cb,
1558                                                                rf_helper);
1559                                 /* Clean */
1560                                 g_object_unref(mail_op);
1561                         } else {
1562                                 /* we put a ref here to prevent double unref as the reply
1563                                  * forward callback unrefs the header at its end */
1564                                 reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
1565                         }
1566
1567
1568                         g_object_unref (header);
1569                 }
1570
1571         }
1572
1573         /* Free */
1574         g_object_unref (header_list);
1575 }
1576
1577 void
1578 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1579 {
1580         g_return_if_fail (MODEST_IS_WINDOW(win));
1581
1582         reply_forward (ACTION_REPLY, win);
1583 }
1584
1585 void
1586 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1587 {
1588         g_return_if_fail (MODEST_IS_WINDOW(win));
1589
1590         reply_forward (ACTION_FORWARD, win);
1591 }
1592
1593 void
1594 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1595 {
1596         g_return_if_fail (MODEST_IS_WINDOW(win));
1597
1598         reply_forward (ACTION_REPLY_TO_ALL, win);
1599 }
1600
1601 void 
1602 modest_ui_actions_on_next (GtkAction *action, 
1603                            ModestWindow *window)
1604 {
1605         if (MODEST_IS_MAIN_WINDOW (window)) {
1606                 GtkWidget *header_view;
1607
1608                 header_view = modest_main_window_get_child_widget (
1609                                 MODEST_MAIN_WINDOW(window),
1610                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1611                 if (!header_view)
1612                         return;
1613         
1614                 modest_header_view_select_next (
1615                                 MODEST_HEADER_VIEW(header_view)); 
1616         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1617                 modest_msg_view_window_select_next_message (
1618                                 MODEST_MSG_VIEW_WINDOW (window));
1619         } else {
1620                 g_return_if_reached ();
1621         }
1622 }
1623
1624 void 
1625 modest_ui_actions_on_prev (GtkAction *action, 
1626                            ModestWindow *window)
1627 {
1628         g_return_if_fail (MODEST_IS_WINDOW(window));
1629
1630         if (MODEST_IS_MAIN_WINDOW (window)) {
1631                 GtkWidget *header_view;
1632                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1633                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1634                 if (!header_view)
1635                         return;
1636                 
1637                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1638         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1639                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1640         } else {
1641                 g_return_if_reached ();
1642         }
1643 }
1644
1645 void 
1646 modest_ui_actions_on_sort (GtkAction *action, 
1647                            ModestWindow *window)
1648 {
1649         g_return_if_fail (MODEST_IS_WINDOW(window));
1650
1651         if (MODEST_IS_MAIN_WINDOW (window)) {
1652                 GtkWidget *header_view;
1653                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1654                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1655                 if (!header_view) {
1656                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1657
1658                         return;
1659                 }
1660
1661                 /* Show sorting dialog */
1662                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1663         }
1664 }
1665
1666 static void
1667 new_messages_arrived (ModestMailOperation *self, 
1668                       TnyList *new_headers,
1669                       gpointer user_data)
1670 {
1671         GObject *source;
1672         gboolean show_visual_notifications;
1673
1674         source = modest_mail_operation_get_source (self);
1675         show_visual_notifications = (source) ? FALSE : TRUE;
1676         if (source)
1677                 g_object_unref (source);
1678
1679         /* Notify new messages have been downloaded. If the
1680            send&receive was invoked by the user then do not show any
1681            visual notification, only play a sound and activate the LED
1682            (for the Maemo version) */
1683         if ((new_headers != NULL) && (tny_list_get_length (new_headers) > 0))
1684                 modest_platform_on_new_headers_received (new_headers, 
1685                                                          show_visual_notifications);
1686
1687 }
1688
1689 gboolean
1690 retrieve_all_messages_cb (GObject *source,
1691                           guint num_msgs,
1692                           guint retrieve_limit)
1693 {
1694         GtkWindow *window;
1695         gchar *msg;
1696         gint response;
1697
1698         window = GTK_WINDOW (source);
1699         msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"), 
1700                                num_msgs, retrieve_limit);
1701
1702         /* Ask the user if they want to retrieve all the messages */
1703         response = 
1704                 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
1705                                                                       _("mcen_bd_get_all"),
1706                                                                       _("mcen_bd_newest_only"));
1707         /* Free and return */
1708         g_free (msg);
1709         return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
1710 }
1711
1712 typedef struct {
1713         TnyAccount *account;
1714         ModestWindow *win;
1715         gchar *account_name;
1716 } SendReceiveInfo;
1717
1718 static void
1719 do_send_receive_performer (gboolean canceled, 
1720                            GError *err,
1721                            GtkWindow *parent_window, 
1722                            TnyAccount *account, 
1723                            gpointer user_data)
1724 {
1725         ModestMailOperation *mail_op;
1726         SendReceiveInfo *info;
1727
1728         info = (SendReceiveInfo *) user_data;
1729
1730         if (err || canceled) {
1731                 goto clean;
1732         }
1733
1734         /* Set send/receive operation in progress */    
1735         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
1736                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
1737         }
1738         
1739         mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
1740                                                                  modest_ui_actions_send_receive_error_handler,
1741                                                                  NULL, NULL);
1742
1743         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
1744                 g_signal_connect (G_OBJECT(mail_op), "operation-finished", 
1745                                   G_CALLBACK (on_send_receive_finished), 
1746                                   info->win);
1747
1748         /* Send & receive. */
1749         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1750         modest_mail_operation_update_account (mail_op, info->account_name, (info->win) ? FALSE : TRUE,
1751                                               (info->win) ? retrieve_all_messages_cb : NULL, 
1752                                               new_messages_arrived, info->win);
1753         g_object_unref (G_OBJECT (mail_op));
1754         
1755  clean:
1756         /* Frees */
1757         if (info->account_name)
1758                 g_free (info->account_name);
1759         if (info->win)
1760                 g_object_unref (info->win);
1761         if (info->account)
1762                 g_object_unref (info->account);
1763         g_slice_free (SendReceiveInfo, info);
1764 }
1765
1766 /*
1767  * This function performs the send & receive required actions. The
1768  * window is used to create the mail operation. Typically it should
1769  * always be the main window, but we pass it as argument in order to
1770  * be more flexible.
1771  */
1772 void
1773 modest_ui_actions_do_send_receive (const gchar *account_name, 
1774                                    gboolean force_connection,
1775                                    ModestWindow *win)
1776 {
1777         gchar *acc_name = NULL;
1778         SendReceiveInfo *info;
1779         ModestTnyAccountStore *acc_store;
1780
1781         /* If no account name was provided then get the current account, and if
1782            there is no current account then pick the default one: */
1783         if (!account_name) {
1784                 if (win)
1785                         acc_name = g_strdup (modest_window_get_active_account (win));
1786                 if (!acc_name)
1787                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1788                 if (!acc_name) {
1789                         g_printerr ("modest: cannot get default account\n");
1790                         return;
1791                 }
1792         } else {
1793                 acc_name = g_strdup (account_name);
1794         }
1795
1796         acc_store = modest_runtime_get_account_store ();
1797
1798         /* Create the info for the connect and perform */
1799         info = g_slice_new (SendReceiveInfo);
1800         info->account_name = acc_name;
1801         info->win = (win) ? g_object_ref (win) : NULL;
1802         info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
1803                                                                      TNY_ACCOUNT_TYPE_STORE);
1804
1805         /* Invoke the connect and perform */
1806         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL, 
1807                                              force_connection, info->account, 
1808                                              do_send_receive_performer, info);
1809 }
1810
1811
1812 static void
1813 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1814                                   ModestWindow *win)
1815 {
1816         TnyTransportAccount *transport_account;
1817         TnySendQueue *send_queue = NULL;
1818         GError *error = NULL;
1819
1820         /* Get transport account */
1821         transport_account =
1822                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1823                                       (modest_runtime_get_account_store(),
1824                                        account_name,
1825                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1826         if (!transport_account) {
1827                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1828                 goto frees;
1829         }
1830
1831         /* Get send queue*/
1832         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1833         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1834                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1835                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1836                              "modest: could not find send queue for account\n");
1837         } else {
1838                 /* Keeep messages in outbox folder */
1839                 tny_send_queue_cancel (send_queue, FALSE, &error);
1840         }       
1841
1842  frees:
1843         if (transport_account != NULL) 
1844                 g_object_unref (G_OBJECT (transport_account));
1845 }
1846
1847 static void
1848 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1849 {
1850         GSList *account_names, *iter;
1851
1852         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1853                                                           TRUE);
1854
1855         iter = account_names;
1856         while (iter) {                  
1857                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1858                 iter = g_slist_next (iter);
1859         }
1860
1861         modest_account_mgr_free_account_names (account_names);
1862         account_names = NULL;
1863 }
1864
1865 void
1866 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1867
1868 {
1869         /* Check if accounts exist */
1870         gboolean accounts_exist = 
1871                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1872         
1873         /* If not, allow the user to create an account before trying to send/receive. */
1874         if (!accounts_exist)
1875                 modest_ui_actions_on_accounts (NULL, win);
1876         
1877         /* Cancel all sending operaitons */     
1878         modest_ui_actions_cancel_send_all (win);
1879 }
1880
1881 /*
1882  * Refreshes all accounts. This function will be used by automatic
1883  * updates
1884  */
1885 void
1886 modest_ui_actions_do_send_receive_all (ModestWindow *win, 
1887                                        gboolean force_connection)
1888 {
1889         GSList *account_names, *iter;
1890
1891         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1892                                                           TRUE);
1893
1894         iter = account_names;
1895         while (iter) {                  
1896                 modest_ui_actions_do_send_receive ((const char*) iter->data, force_connection, win);
1897                 iter = g_slist_next (iter);
1898         }
1899
1900         modest_account_mgr_free_account_names (account_names);
1901         account_names = NULL;
1902 }
1903
1904 /*
1905  * Handler of the click on Send&Receive button in the main toolbar
1906  */
1907 void
1908 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1909 {
1910         /* Check if accounts exist */
1911         gboolean accounts_exist;
1912
1913         accounts_exist =
1914                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1915         
1916         /* If not, allow the user to create an account before trying to send/receive. */
1917         if (!accounts_exist)
1918                 modest_ui_actions_on_accounts (NULL, win);
1919         
1920         /* Refresh the current folder. The if is always TRUE it's just an extra check */
1921         if (MODEST_IS_MAIN_WINDOW (win)) {
1922                 GtkWidget *folder_view;
1923                 TnyFolderStore *folder_store;
1924
1925                 folder_view = 
1926                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1927                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1928                 if (!folder_view)
1929                         return;
1930                 
1931                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1932         
1933                 if (folder_store)
1934                         g_object_unref (folder_store);
1935         }       
1936         
1937         /* Refresh the active account. Force the connection if needed */
1938         modest_ui_actions_do_send_receive (NULL, TRUE, win);
1939 }
1940
1941
1942 void
1943 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1944 {
1945         ModestConf *conf;
1946         GtkWidget *header_view;
1947         
1948         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1949
1950         header_view = modest_main_window_get_child_widget (main_window,
1951                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1952         if (!header_view)
1953                 return;
1954
1955         conf = modest_runtime_get_conf ();
1956         
1957         /* what is saved/restored is depending on the style; thus; we save with
1958          * old style, then update the style, and restore for this new style
1959          */
1960         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1961         
1962         if (modest_header_view_get_style
1963             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1964                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1965                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1966         else
1967                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1968                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1969
1970         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1971                                       MODEST_CONF_HEADER_VIEW_KEY);
1972 }
1973
1974
1975 void 
1976 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1977                                       TnyHeader *header,
1978                                       ModestMainWindow *main_window)
1979 {
1980         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1981         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1982         
1983         /* in the case the folder is empty, show the empty folder message and focus
1984          * folder view */
1985         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1986                 if (modest_header_view_is_empty (header_view)) {
1987                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1988                         GtkWidget *folder_view = 
1989                                 modest_main_window_get_child_widget (main_window,
1990                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1991                         if (folder != NULL) 
1992                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1993                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1994                         return;
1995                 }
1996         }
1997         /* If no header has been selected then exit */
1998         if (!header)
1999                 return;
2000
2001         /* Update focus */
2002         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2003             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2004
2005         /* Update toolbar dimming state */
2006         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2007 }
2008
2009 void
2010 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2011                                        TnyHeader *header,
2012                                        ModestMainWindow *main_window)
2013 {
2014         TnyList *headers;
2015
2016         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2017
2018         if (!header)
2019                 return;
2020
2021         if (modest_header_view_count_selected_headers (header_view) > 1) {
2022                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2023                 return;
2024         }
2025
2026
2027 /*      headers = tny_simple_list_new (); */
2028 /*      tny_list_prepend (headers, G_OBJECT (header)); */
2029         headers = modest_header_view_get_selected_headers (header_view);
2030
2031         open_msgs_from_headers (headers, MODEST_WINDOW (main_window));
2032
2033         g_object_unref (headers);
2034 }
2035
2036 static void
2037 set_active_account_from_tny_account (TnyAccount *account,
2038                                      ModestWindow *window)
2039 {
2040         const gchar *server_acc_name = tny_account_get_id (account);
2041         
2042         /* We need the TnyAccount provided by the
2043            account store because that is the one that
2044            knows the name of the Modest account */
2045         TnyAccount *modest_server_account = modest_server_account = 
2046                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2047                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
2048                                                              server_acc_name);
2049         if (!modest_server_account) {
2050                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2051                 return;
2052         }
2053
2054         /* Update active account, but only if it's not a pseudo-account */
2055         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2056             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2057                 const gchar *modest_acc_name = 
2058                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2059                 if (modest_acc_name)
2060                         modest_window_set_active_account (window, modest_acc_name);
2061         }
2062         
2063         g_object_unref (modest_server_account);
2064 }
2065
2066
2067 static void
2068 folder_refreshed_cb (ModestMailOperation *mail_op, 
2069                      TnyFolder *folder, 
2070                      gpointer user_data)
2071 {
2072         ModestMainWindow *win = NULL;
2073         GtkWidget *header_view;
2074
2075         g_return_if_fail (TNY_IS_FOLDER (folder));
2076
2077         win = MODEST_MAIN_WINDOW (user_data);
2078         header_view = 
2079                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2080
2081         if (header_view) {
2082                 TnyFolder *current_folder;
2083
2084                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2085                 if (current_folder != NULL && folder != current_folder) {
2086                         g_object_unref (current_folder);
2087                         return;
2088                 } else if (current_folder)
2089                         g_object_unref (current_folder);
2090         }
2091
2092         /* Check if folder is empty and set headers view contents style */
2093         if (tny_folder_get_all_count (folder) == 0)
2094                 modest_main_window_set_contents_style (win,
2095                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2096 }
2097
2098 void 
2099 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2100                                                TnyFolderStore *folder_store, 
2101                                                gboolean selected,
2102                                                ModestMainWindow *main_window)
2103 {
2104         ModestConf *conf;
2105         GtkWidget *header_view;
2106
2107         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2108
2109         header_view = modest_main_window_get_child_widget(main_window,
2110                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2111         if (!header_view)
2112                 return;
2113         
2114         conf = modest_runtime_get_conf ();
2115
2116         if (TNY_IS_ACCOUNT (folder_store)) {
2117                 if (selected) {
2118                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2119                         
2120                         /* Show account details */
2121                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2122                 }
2123         } else {
2124                 if (TNY_IS_FOLDER (folder_store) && selected) {
2125                         
2126                         /* Update the active account */
2127                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2128                         if (account) {
2129                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2130                                 g_object_unref (account);
2131                                 account = NULL;
2132                         }
2133
2134                         /* Set the header style by default, it could
2135                            be changed later by the refresh callback to
2136                            empty */
2137                         modest_main_window_set_contents_style (main_window, 
2138                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2139
2140                         /* Set folder on header view. This function
2141                            will call tny_folder_refresh_async so we
2142                            pass a callback that will be called when
2143                            finished. We use that callback to set the
2144                            empty view if there are no messages */
2145                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2146                                                        TNY_FOLDER (folder_store),
2147                                                        folder_refreshed_cb,
2148                                                        main_window);
2149                         
2150                         /* Restore configuration. We need to do this
2151                            *after* the set_folder because the widget
2152                            memory asks the header view about its
2153                            folder  */
2154                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2155                                                       G_OBJECT(header_view),
2156                                                       MODEST_CONF_HEADER_VIEW_KEY);
2157                 } else {
2158                         /* Update the active account */
2159                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2160                         /* Save only if we're seeing headers */
2161                         if (modest_main_window_get_contents_style (main_window) ==
2162                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2163                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2164                                                            MODEST_CONF_HEADER_VIEW_KEY);
2165                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2166                 }
2167         }
2168
2169         /* Update toolbar dimming state */
2170         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2171 }
2172
2173 void 
2174 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2175                                      ModestWindow *win)
2176 {
2177         GtkWidget *dialog;
2178         gchar *txt, *item;
2179         gboolean online;
2180
2181         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2182         
2183         online = tny_device_is_online (modest_runtime_get_device());
2184
2185         if (online) {
2186                 /* already online -- the item is simply not there... */
2187                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2188                                                  GTK_DIALOG_MODAL,
2189                                                  GTK_MESSAGE_WARNING,
2190                                                  GTK_BUTTONS_NONE,
2191                                                  _("The %s you selected cannot be found"),
2192                                                  item);
2193                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2194                 gtk_dialog_run (GTK_DIALOG(dialog));
2195         } else {
2196                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2197                                                       GTK_WINDOW (win),
2198                                                       GTK_DIALOG_MODAL,
2199                                                       _("mcen_bd_dialog_cancel"),
2200                                                       GTK_RESPONSE_REJECT,
2201                                                       _("mcen_bd_dialog_ok"),
2202                                                       GTK_RESPONSE_ACCEPT,
2203                                                       NULL);
2204                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2205                                          "Do you want to get online?"), item);
2206                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2207                                     gtk_label_new (txt), FALSE, FALSE, 0);
2208                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2209                 g_free (txt);
2210
2211                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2212                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2213                         /* TODO: Comment about why is this commented out: */
2214                         /* modest_platform_connect_and_wait (); */
2215                 }
2216         }
2217         gtk_widget_destroy (dialog);
2218 }
2219
2220 void
2221 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2222                                      ModestWindow *win)
2223 {
2224         /* g_message ("%s %s", __FUNCTION__, link); */
2225 }       
2226
2227
2228 void
2229 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2230                                         ModestWindow *win)
2231 {
2232         modest_platform_activate_uri (link);
2233 }
2234
2235 void
2236 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2237                                           ModestWindow *win)
2238 {
2239         modest_platform_show_uri_popup (link);
2240 }
2241
2242 void
2243 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2244                                              ModestWindow *win)
2245 {
2246         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2247 }
2248
2249 void
2250 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2251                                           const gchar *address,
2252                                           ModestWindow *win)
2253 {
2254         /* g_message ("%s %s", __FUNCTION__, address); */
2255 }
2256
2257 static void
2258 on_save_to_drafts_cb (ModestMailOperation *mail_op, 
2259                       TnyMsg *saved_draft,
2260                       gpointer user_data)
2261 {
2262         ModestMsgEditWindow *edit_window;
2263         ModestMainWindow *win;
2264
2265         /* FIXME. Make the header view sensitive again. This is a
2266          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2267          * for details */
2268         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2269                                          modest_runtime_get_window_mgr(), FALSE));
2270         if (win != NULL) {
2271                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2272                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2273                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2274         }
2275
2276         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2277
2278         /* It might not be a good idea to do nothing if there was an error,
2279          * so let's at least show a generic error banner. */
2280         /* TODO error while saving attachment, show "Saving draft failed" banner */
2281         if (modest_mail_operation_get_error (mail_op) != NULL) {
2282                 g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_op))->message);
2283                 modest_platform_information_banner (NULL, NULL, _("mail_ib_file_operation_failed"));
2284         } else {
2285                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2286         }
2287         g_object_unref(edit_window);
2288 }
2289
2290 void
2291 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2292 {
2293         TnyTransportAccount *transport_account;
2294         ModestMailOperation *mail_operation;
2295         MsgData *data;
2296         gchar *account_name, *from;
2297         ModestAccountMgr *account_mgr;
2298         char *info_text;
2299
2300         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2301         
2302         data = modest_msg_edit_window_get_msg_data (edit_window);
2303
2304         account_name = g_strdup (data->account_name);
2305         account_mgr = modest_runtime_get_account_mgr();
2306         if (!account_name)
2307                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2308         if (!account_name) 
2309                 account_name = modest_account_mgr_get_default_account (account_mgr);
2310         if (!account_name) {
2311                 g_printerr ("modest: no account found\n");
2312                 modest_msg_edit_window_free_msg_data (edit_window, data);
2313                 return;
2314         }
2315
2316         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2317                 account_name = g_strdup (data->account_name);
2318         }
2319
2320         transport_account =
2321                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2322                                       (modest_runtime_get_account_store(),
2323                                        account_name,
2324                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2325         if (!transport_account) {
2326                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2327                 g_free (account_name);
2328                 modest_msg_edit_window_free_msg_data (edit_window, data);
2329                 return;
2330         }
2331         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2332
2333         /* Create the mail operation */         
2334         mail_operation = modest_mail_operation_new (NULL);
2335         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2336
2337         modest_mail_operation_save_to_drafts (mail_operation,
2338                                               transport_account,
2339                                               data->draft_msg,
2340                                               from,
2341                                               data->to, 
2342                                               data->cc, 
2343                                               data->bcc,
2344                                               data->subject, 
2345                                               data->plain_body, 
2346                                               data->html_body,
2347                                               data->attachments,
2348                                               data->images,
2349                                               data->priority_flags,
2350                                               on_save_to_drafts_cb,
2351                                               g_object_ref(edit_window));
2352         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2353         modest_platform_information_banner (NULL, NULL, info_text);
2354
2355         /* Frees */
2356         g_free (info_text);
2357         g_free (from);
2358         g_free (account_name);
2359         g_object_unref (G_OBJECT (transport_account));
2360         g_object_unref (G_OBJECT (mail_operation));
2361
2362         modest_msg_edit_window_free_msg_data (edit_window, data);
2363         modest_msg_edit_window_reset_modified (edit_window);
2364
2365         /* ** FIXME **
2366          * If the drafts folder is selected then make the header view
2367          * insensitive while the message is being saved to drafts
2368          * (it'll be sensitive again in on_save_to_drafts_cb()). This
2369          * is not very clean but it avoids letting the drafts folder
2370          * in an inconsistent state: the user could edit the message
2371          * being saved and undesirable things would happen.
2372          * In the average case the user won't notice anything at
2373          * all. In the worst case (the user is editing a really big
2374          * file from Drafts) the header view will be insensitive
2375          * during the saving process (10 or 20 seconds, depending on
2376          * the message). Anyway this is just a quick workaround: once
2377          * we find a better solution it should be removed
2378          * See NB#65125 (commend #18) for details.
2379          */
2380         ModestMainWindow *win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2381                 modest_runtime_get_window_mgr(), FALSE));
2382         if (win != NULL) {
2383                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2384                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2385                 if (view != NULL) {
2386                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2387                         if (folder) {
2388                                 if (modest_tny_folder_is_local_folder(folder)) {
2389                                         TnyFolderType folder_type;
2390                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2391                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2392                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2393                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2394                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2395                                         }
2396                                 }
2397                         }
2398                         if (folder != NULL) g_object_unref(folder);
2399                 }
2400         }
2401 }
2402
2403 /* For instance, when clicking the Send toolbar button when editing a message: */
2404 void
2405 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2406 {
2407         TnyTransportAccount *transport_account = NULL;
2408
2409         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2410
2411         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2412                 return;
2413         
2414         /* FIXME: Code added just for testing. The final version will
2415            use the send queue provided by tinymail and some
2416            classifier */
2417         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2418
2419         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2420         gchar *account_name = g_strdup (data->account_name);
2421         if (!account_name)
2422                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2423
2424         if (!account_name) 
2425                 account_name = modest_account_mgr_get_default_account (account_mgr);
2426                 
2427         if (!account_name) {
2428                 modest_msg_edit_window_free_msg_data (edit_window, data);
2429                 /* Run account setup wizard */
2430                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
2431                         return;
2432                 }
2433         }
2434         
2435         /* Get the currently-active transport account for this modest account: */
2436         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2437                 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2438                                                           (modest_runtime_get_account_store(),
2439                                                            account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2440         }
2441         
2442         if (!transport_account) {
2443                 modest_msg_edit_window_free_msg_data (edit_window, data);
2444                 /* Run account setup wizard */
2445                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2446                         return;
2447         }
2448         
2449         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2450
2451         /* Create the mail operation */
2452         ModestMailOperation *mail_operation = modest_mail_operation_new (NULL);
2453         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2454
2455         modest_mail_operation_send_new_mail (mail_operation,
2456                                              transport_account,
2457                                              data->draft_msg,
2458                                              from,
2459                                              data->to, 
2460                                              data->cc, 
2461                                              data->bcc,
2462                                              data->subject, 
2463                                              data->plain_body, 
2464                                              data->html_body,
2465                                              data->attachments,
2466                                              data->images,
2467                                              data->priority_flags);
2468
2469         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2470                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2471
2472                                              
2473         /* Free data: */
2474         g_free (from);
2475         g_free (account_name);
2476         g_object_unref (G_OBJECT (transport_account));
2477         g_object_unref (G_OBJECT (mail_operation));
2478
2479         modest_msg_edit_window_free_msg_data (edit_window, data);
2480         modest_msg_edit_window_set_sent (edit_window, TRUE);
2481
2482         /* Save settings and close the window: */
2483         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2484 }
2485
2486 void 
2487 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2488                                   ModestMsgEditWindow *window)
2489 {
2490         ModestMsgEditFormatState *format_state = NULL;
2491
2492         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2493         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2494
2495         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2496                 return;
2497
2498         format_state = modest_msg_edit_window_get_format_state (window);
2499         g_return_if_fail (format_state != NULL);
2500
2501         format_state->bold = gtk_toggle_action_get_active (action);
2502         modest_msg_edit_window_set_format_state (window, format_state);
2503         g_free (format_state);
2504         
2505 }
2506
2507 void 
2508 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2509                                      ModestMsgEditWindow *window)
2510 {
2511         ModestMsgEditFormatState *format_state = NULL;
2512
2513         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2514         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2515
2516         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2517                 return;
2518
2519         format_state = modest_msg_edit_window_get_format_state (window);
2520         g_return_if_fail (format_state != NULL);
2521
2522         format_state->italics = gtk_toggle_action_get_active (action);
2523         modest_msg_edit_window_set_format_state (window, format_state);
2524         g_free (format_state);
2525         
2526 }
2527
2528 void 
2529 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2530                                      ModestMsgEditWindow *window)
2531 {
2532         ModestMsgEditFormatState *format_state = NULL;
2533
2534         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2535         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2536
2537         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2538                 return;
2539
2540         format_state = modest_msg_edit_window_get_format_state (window);
2541         g_return_if_fail (format_state != NULL);
2542
2543         format_state->bullet = gtk_toggle_action_get_active (action);
2544         modest_msg_edit_window_set_format_state (window, format_state);
2545         g_free (format_state);
2546         
2547 }
2548
2549 void 
2550 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2551                                      GtkRadioAction *selected,
2552                                      ModestMsgEditWindow *window)
2553 {
2554         ModestMsgEditFormatState *format_state = NULL;
2555         GtkJustification value;
2556
2557         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2558
2559         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2560                 return;
2561
2562         value = gtk_radio_action_get_current_value (selected);
2563
2564         format_state = modest_msg_edit_window_get_format_state (window);
2565         g_return_if_fail (format_state != NULL);
2566
2567         format_state->justification = value;
2568         modest_msg_edit_window_set_format_state (window, format_state);
2569         g_free (format_state);
2570 }
2571
2572 void 
2573 modest_ui_actions_on_select_editor_color (GtkAction *action,
2574                                           ModestMsgEditWindow *window)
2575 {
2576         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2577         g_return_if_fail (GTK_IS_ACTION (action));
2578
2579         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2580                 return;
2581
2582         modest_msg_edit_window_select_color (window);
2583 }
2584
2585 void 
2586 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2587                                                      ModestMsgEditWindow *window)
2588 {
2589         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2590         g_return_if_fail (GTK_IS_ACTION (action));
2591
2592         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2593                 return;
2594
2595         modest_msg_edit_window_select_background_color (window);
2596 }
2597
2598 void 
2599 modest_ui_actions_on_insert_image (GtkAction *action,
2600                                    ModestMsgEditWindow *window)
2601 {
2602         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2603         g_return_if_fail (GTK_IS_ACTION (action));
2604
2605         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2606                 return;
2607
2608         modest_msg_edit_window_insert_image (window);
2609 }
2610
2611 void 
2612 modest_ui_actions_on_attach_file (GtkAction *action,
2613                                   ModestMsgEditWindow *window)
2614 {
2615         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2616         g_return_if_fail (GTK_IS_ACTION (action));
2617
2618         modest_msg_edit_window_offer_attach_file (window);
2619 }
2620
2621 void 
2622 modest_ui_actions_on_remove_attachments (GtkAction *action,
2623                                          ModestMsgEditWindow *window)
2624 {
2625         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2626         g_return_if_fail (GTK_IS_ACTION (action));
2627
2628         modest_msg_edit_window_remove_attachments (window, NULL);
2629 }
2630
2631 static void
2632 do_create_folder_cb (ModestMailOperation *mail_op,
2633                      TnyFolderStore *parent_folder, 
2634                      TnyFolder *new_folder,
2635                      gpointer user_data)
2636 {
2637         gchar *suggested_name = (gchar *) user_data;
2638         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
2639
2640         if (modest_mail_operation_get_error (mail_op)) {
2641                 /* Show an error */
2642                 modest_platform_information_banner (GTK_WIDGET (source_win), NULL,
2643                                                     _("mail_in_ui_folder_create_error"));
2644
2645                 /* Try again */
2646                 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
2647         } else {
2648                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
2649                  * FIXME: any other? */         
2650                 GtkWidget *folder_view;
2651
2652                 if (MODEST_IS_MAIN_WINDOW(source_win)) 
2653                         folder_view = 
2654                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
2655                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2656                 else
2657                         folder_view =
2658                                 get_folder_view_from_move_to_dialog (GTK_WIDGET(source_win));
2659                 
2660                 /* Select the newly created folder */
2661                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
2662                                                   new_folder, FALSE);
2663                 g_object_unref (new_folder);
2664         }
2665         /* Free. Note that the first time it'll be NULL so noop */
2666         g_free (suggested_name);
2667         g_object_unref (source_win);
2668 }
2669
2670 static void
2671 do_create_folder (GtkWindow *parent_window, 
2672                   TnyFolderStore *parent_folder, 
2673                   const gchar *suggested_name)
2674 {
2675         gint result;
2676         gchar *folder_name = NULL;
2677
2678         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2679                                                         parent_folder,
2680                                                         (gchar *) suggested_name,
2681                                                         &folder_name);
2682         
2683         if (result == GTK_RESPONSE_ACCEPT) {
2684                 ModestMailOperation *mail_op;
2685                 
2686                 mail_op  = modest_mail_operation_new (G_OBJECT(parent_window));
2687                         
2688                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2689                                                  mail_op);
2690                 modest_mail_operation_create_folder (mail_op,
2691                                                      parent_folder,
2692                                                      (const gchar *) folder_name,
2693                                                      do_create_folder_cb,
2694                                                      folder_name);
2695                 g_object_unref (mail_op);
2696         }
2697 }
2698
2699 static void
2700 create_folder_performer (gboolean canceled, 
2701                          GError *err,
2702                          GtkWindow *parent_window, 
2703                          TnyAccount *account, 
2704                          gpointer user_data)
2705 {
2706         TnyFolderStore *parent_folder = TNY_FOLDER_STORE (user_data);
2707
2708         if (canceled || err) {
2709                 goto frees;
2710         }
2711
2712         /* Run the new folder dialog */
2713         do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
2714
2715  frees:
2716         g_object_unref (parent_folder);
2717 }
2718
2719 static void
2720 modest_ui_actions_create_folder(GtkWidget *parent_window,
2721                                 GtkWidget *folder_view)
2722 {
2723         TnyFolderStore *parent_folder;
2724
2725         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2726         
2727         if (parent_folder) {
2728                 /* The parent folder will be freed in the callback */
2729                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window), 
2730                                                                TRUE,
2731                                                                parent_folder,
2732                                                                create_folder_performer, 
2733                                                                parent_folder);
2734         }
2735 }
2736
2737 void 
2738 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2739 {
2740         GtkWidget *folder_view;
2741         
2742         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2743
2744         folder_view = modest_main_window_get_child_widget (main_window,
2745                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2746         if (!folder_view)
2747                 return;
2748
2749         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2750 }
2751
2752 static void
2753 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2754                                                gpointer user_data)
2755 {
2756         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2757         const GError *error = NULL;
2758         const gchar *message = NULL;
2759         
2760         /* Get error message */
2761         error = modest_mail_operation_get_error (mail_op);
2762         if (!error)
2763                 g_return_if_reached ();
2764
2765         switch (error->code) {
2766         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2767                 message = _CS("ckdg_ib_folder_already_exists");
2768                 break;
2769         default:
2770                 g_warning ("%s: BUG: unexpected error:[%d]: %s", __FUNCTION__,
2771                            error->code, error->message);
2772                 return;
2773         }
2774
2775         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2776 }
2777
2778 typedef struct {
2779         TnyFolderStore *folder;
2780         gchar *new_name;
2781 } RenameFolderInfo;
2782
2783 static void
2784 on_rename_folder_cb (ModestMailOperation *mail_op, 
2785                      TnyFolder *new_folder,
2786                      gpointer user_data)
2787 {
2788         /* Select now */
2789         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (user_data),
2790                                           new_folder, FALSE);
2791 }
2792
2793 static void
2794 on_rename_folder_performer (gboolean canceled, 
2795                             GError *err, 
2796                             GtkWindow *parent_window, 
2797                             TnyAccount *account, 
2798                             gpointer user_data)
2799 {
2800         ModestMailOperation *mail_op = NULL;
2801         GtkTreeSelection *sel = NULL;
2802         GtkWidget *folder_view = NULL;
2803         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
2804
2805         if (!canceled && (err == NULL) && MODEST_IS_MAIN_WINDOW(parent_window)) {
2806
2807                 folder_view = modest_main_window_get_child_widget (
2808                                 MODEST_MAIN_WINDOW (parent_window),
2809                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2810
2811                 mail_op = 
2812                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2813                                         modest_ui_actions_rename_folder_error_handler,
2814                                         parent_window, NULL);
2815
2816                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2817                                 mail_op);
2818
2819                 /* Clear the headers view */
2820                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2821                 gtk_tree_selection_unselect_all (sel);
2822
2823                 /* Actually rename the folder */
2824                 modest_mail_operation_rename_folder (mail_op,
2825                                                      TNY_FOLDER (data->folder),
2826                                                      (const gchar *) (data->new_name),
2827                                                      on_rename_folder_cb,
2828                                                      folder_view);
2829         }
2830
2831         g_object_unref (mail_op);
2832         g_free (data->new_name);
2833         g_free (data);
2834 }
2835
2836 void 
2837 modest_ui_actions_on_rename_folder (GtkAction *action,
2838                                      ModestMainWindow *main_window)
2839 {
2840         TnyFolderStore *folder;
2841         GtkWidget *folder_view;
2842         GtkWidget *header_view; 
2843
2844         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2845
2846         folder_view = modest_main_window_get_child_widget (main_window,
2847                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2848         if (!folder_view)
2849                 return;
2850
2851         header_view = modest_main_window_get_child_widget (main_window,
2852                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2853         
2854         if (!header_view)
2855                 return;
2856
2857         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2858
2859         if (!folder)
2860                 return;
2861
2862         if (TNY_IS_FOLDER (folder)) {
2863                 gchar *folder_name;
2864                 gint response;
2865                 const gchar *current_name;
2866                 TnyFolderStore *parent;
2867                 gboolean do_rename = TRUE;
2868
2869                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2870                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2871                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2872                                                                      parent, current_name, 
2873                                                                      &folder_name);
2874                 g_object_unref (parent);
2875
2876                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2877                         do_rename = FALSE;
2878                 } else {
2879                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
2880                         rename_folder_data->folder = folder;
2881                         rename_folder_data->new_name = folder_name;
2882                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), TRUE,
2883                                         folder, on_rename_folder_performer, rename_folder_data);
2884                 }
2885         }
2886         g_object_unref (folder);
2887 }
2888
2889 static void
2890 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2891                                                gpointer user_data)
2892 {
2893         GObject *win = modest_mail_operation_get_source (mail_op);
2894
2895         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2896                                                 _("mail_in_ui_folder_delete_error"));
2897         g_object_unref (win);
2898 }
2899
2900 typedef struct {
2901         TnyFolderStore *folder;
2902         gboolean move_to_trash;
2903 } DeleteFolderInfo;
2904
2905 static void
2906 on_delete_folder_cb (gboolean canceled, 
2907                   GError *err,
2908                   GtkWindow *parent_window, 
2909                   TnyAccount *account, 
2910                   gpointer user_data)
2911 {
2912         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
2913         GtkWidget *folder_view;
2914         ModestMailOperation *mail_op;
2915         GtkTreeSelection *sel;
2916         
2917         if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
2918                 g_object_unref (G_OBJECT (info->folder));
2919                 g_free (info);
2920         }
2921         
2922         folder_view = modest_main_window_get_child_widget (
2923                         MODEST_MAIN_WINDOW (parent_window),
2924                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2925
2926         /* Unselect the folder before deleting it to free the headers */
2927         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2928         gtk_tree_selection_unselect_all (sel);
2929
2930         /* Create the mail operation */
2931         mail_op =
2932                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2933                                 modest_ui_actions_delete_folder_error_handler,
2934                                 NULL, NULL);
2935
2936         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2937                         mail_op);
2938         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
2939         
2940         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2941
2942         g_object_unref (G_OBJECT (mail_op));
2943         g_object_unref (G_OBJECT (info->folder));
2944         g_free (info);
2945 }
2946
2947 static void
2948 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
2949 {
2950         TnyFolderStore *folder;
2951         GtkWidget *folder_view;
2952         gint response;
2953         gchar *message;
2954         
2955         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2956
2957         folder_view = modest_main_window_get_child_widget (main_window,
2958                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2959         if (!folder_view)
2960                 return;
2961
2962         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2963
2964         /* Show an error if it's an account */
2965         if (!TNY_IS_FOLDER (folder)) {
2966                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2967                                                         _("mail_in_ui_folder_delete_error"));
2968                 g_object_unref (G_OBJECT (folder));
2969                 return;
2970         }
2971
2972         /* Ask the user */      
2973         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2974                                     tny_folder_get_name (TNY_FOLDER (folder)));
2975         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2976                                                             (const gchar *) message);
2977         g_free (message);
2978
2979         if (response == GTK_RESPONSE_OK) {
2980                 DeleteFolderInfo *info;
2981                 info = g_new0(DeleteFolderInfo, 1);
2982                 info->folder = folder;
2983                 info->move_to_trash = move_to_trash;
2984                 g_object_ref (G_OBJECT (info->folder));
2985                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
2986                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (main_window), 
2987                                                                TRUE,
2988                                                                TNY_FOLDER_STORE (account), 
2989                                                                on_delete_folder_cb, info);
2990                 g_object_unref (account);
2991         }
2992         g_object_unref (G_OBJECT (folder));
2993 }
2994
2995 void 
2996 modest_ui_actions_on_delete_folder (GtkAction *action,
2997                                      ModestMainWindow *main_window)
2998 {
2999         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3000         
3001         delete_folder (main_window, FALSE);
3002 }
3003
3004 void 
3005 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3006 {
3007         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3008         
3009         delete_folder (main_window, TRUE);
3010 }
3011
3012
3013 static void
3014 show_error (GtkWidget *parent_widget, const gchar* text)
3015 {
3016         modest_platform_information_banner(parent_widget, NULL, text);
3017         
3018 #if 0
3019         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
3020         /*
3021           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
3022           (GtkDialogFlags)0,
3023           GTK_MESSAGE_ERROR,
3024           GTK_BUTTONS_OK,
3025           text ));
3026         */
3027                  
3028         gtk_dialog_run (dialog);
3029         gtk_widget_destroy (GTK_WIDGET (dialog));
3030 #endif
3031 }
3032
3033 void
3034 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
3035                                          const gchar* server_account_name,
3036                                          gchar **username,
3037                                          gchar **password, 
3038                                          gboolean *cancel, 
3039                                          gboolean *remember,
3040                                          ModestMainWindow *main_window)
3041 {
3042         g_return_if_fail(server_account_name);
3043         
3044         /* Initalize output parameters: */
3045         if (cancel)
3046                 *cancel = FALSE;
3047                 
3048         if (remember)
3049                 *remember = TRUE;
3050                 
3051 #ifdef MODEST_PLATFORM_MAEMO
3052         /* Maemo uses a different (awkward) button order,
3053          * It should probably just use gtk_alternative_dialog_button_order ().
3054          */
3055         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3056                                               NULL,
3057                                               GTK_DIALOG_MODAL,
3058                                               _("mcen_bd_dialog_ok"),
3059                                               GTK_RESPONSE_ACCEPT,
3060                                               _("mcen_bd_dialog_cancel"),
3061                                               GTK_RESPONSE_REJECT,
3062                                               NULL);
3063 #else
3064         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3065                                               NULL,
3066                                               GTK_DIALOG_MODAL,
3067                                               GTK_STOCK_CANCEL,
3068                                               GTK_RESPONSE_REJECT,
3069                                               GTK_STOCK_OK,
3070                                               GTK_RESPONSE_ACCEPT,
3071                                               NULL);
3072 #endif /* MODEST_PLATFORM_MAEMO */
3073
3074         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3075         
3076         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3077                 modest_runtime_get_account_mgr(), server_account_name);
3078         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3079                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3080                 if (cancel)
3081                         *cancel = TRUE;
3082                 return;
3083         }
3084         
3085         /* This causes a warning because the logical ID has no %s in it, 
3086          * though the translation does, but there is not much we can do about that: */
3087         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3088         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3089                             FALSE, FALSE, 0);
3090         g_free (txt);
3091         g_free (server_name);
3092         server_name = NULL;
3093
3094         /* username: */
3095         gchar *initial_username = modest_account_mgr_get_server_account_username (
3096                 modest_runtime_get_account_mgr(), server_account_name);
3097         
3098         GtkWidget *entry_username = gtk_entry_new ();
3099         if (initial_username)
3100                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3101         /* Dim this if a connection has ever succeeded with this username,
3102          * as per the UI spec: */
3103         const gboolean username_known = 
3104                 modest_account_mgr_get_server_account_username_has_succeeded(
3105                         modest_runtime_get_account_mgr(), server_account_name);
3106         gtk_widget_set_sensitive (entry_username, !username_known);
3107         
3108 #ifdef MODEST_PLATFORM_MAEMO
3109         /* Auto-capitalization is the default, so let's turn it off: */
3110         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3111         
3112         /* Create a size group to be used by all captions.
3113          * Note that HildonCaption does not create a default size group if we do not specify one.
3114          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3115         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3116         
3117         GtkWidget *caption = hildon_caption_new (sizegroup, 
3118                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3119         gtk_widget_show (entry_username);
3120         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3121                 FALSE, FALSE, MODEST_MARGIN_HALF);
3122         gtk_widget_show (caption);
3123 #else 
3124         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3125                             TRUE, FALSE, 0);
3126 #endif /* MODEST_PLATFORM_MAEMO */      
3127                             
3128         /* password: */
3129         GtkWidget *entry_password = gtk_entry_new ();
3130         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3131         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3132         
3133 #ifdef MODEST_PLATFORM_MAEMO
3134         /* Auto-capitalization is the default, so let's turn it off: */
3135         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
3136                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3137         
3138         caption = hildon_caption_new (sizegroup, 
3139                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3140         gtk_widget_show (entry_password);
3141         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3142                 FALSE, FALSE, MODEST_MARGIN_HALF);
3143         gtk_widget_show (caption);
3144         g_object_unref (sizegroup);
3145 #else 
3146         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3147                             TRUE, FALSE, 0);
3148 #endif /* MODEST_PLATFORM_MAEMO */      
3149
3150         if (initial_username != NULL)
3151                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3152                                 
3153 /* This is not in the Maemo UI spec:
3154         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3155         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3156                             TRUE, FALSE, 0);
3157 */
3158
3159         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3160         
3161         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3162                 if (username) {
3163                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3164                         
3165                         modest_account_mgr_set_server_account_username (
3166                                  modest_runtime_get_account_mgr(), server_account_name, 
3167                                  *username);
3168                                  
3169                         const gboolean username_was_changed = 
3170                                 (strcmp (*username, initial_username) != 0);
3171                         if (username_was_changed) {
3172                                 g_warning ("%s: tinymail does not yet support changing the "
3173                                         "username in the get_password() callback.\n", __FUNCTION__);
3174                         }
3175                 }
3176                         
3177                 if (password) {
3178                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3179                         
3180                         /* We do not save the password in the configuration, 
3181                          * because this function is only called for passwords that should 
3182                          * not be remembered:
3183                         modest_server_account_set_password (
3184                                  modest_runtime_get_account_mgr(), server_account_name, 
3185                                  *password);
3186                         */
3187                 }
3188                 
3189                 if (cancel)
3190                         *cancel   = FALSE;
3191                         
3192         } else {
3193                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
3194                 
3195                 if (username)
3196                         *username = NULL;
3197                         
3198                 if (password)
3199                         *password = NULL;
3200                         
3201                 if (cancel)
3202                         *cancel   = TRUE;
3203         }
3204
3205 /* This is not in the Maemo UI spec:
3206         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3207                 *remember = TRUE;
3208         else
3209                 *remember = FALSE;
3210 */
3211
3212         gtk_widget_destroy (dialog);
3213         
3214         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3215 }
3216
3217 void
3218 modest_ui_actions_on_cut (GtkAction *action,
3219                           ModestWindow *window)
3220 {
3221         GtkWidget *focused_widget;
3222         GtkClipboard *clipboard;
3223
3224         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3225         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3226         if (GTK_IS_EDITABLE (focused_widget)) {
3227                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3228                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3229                 gtk_clipboard_store (clipboard);
3230         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3231                 GtkTextBuffer *buffer;
3232
3233                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3234                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3235                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3236                 gtk_clipboard_store (clipboard);
3237         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3238                 TnyList *header_list = modest_header_view_get_selected_headers (
3239                                 MODEST_HEADER_VIEW (focused_widget));
3240                 gboolean continue_download = FALSE;
3241                 gint num_of_unc_msgs;
3242
3243                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3244
3245                 if (num_of_unc_msgs) {
3246                         TnyAccount *account = get_account_from_header_list (header_list);
3247                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3248                         g_object_unref (account);
3249                 }
3250
3251                 if (num_of_unc_msgs == 0 || continue_download) {
3252 /*                      modest_platform_information_banner (
3253                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3254                         modest_header_view_cut_selection (
3255                                         MODEST_HEADER_VIEW (focused_widget));
3256                 }
3257
3258                 g_object_unref (header_list);
3259         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3260                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3261         }
3262 }
3263
3264 void
3265 modest_ui_actions_on_copy (GtkAction *action,
3266                            ModestWindow *window)
3267 {
3268         GtkClipboard *clipboard;
3269         GtkWidget *focused_widget;
3270         gboolean copied = TRUE;
3271
3272         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3273         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3274
3275         if (GTK_IS_LABEL (focused_widget)) {
3276                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
3277                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3278                 gtk_clipboard_store (clipboard);
3279         } else if (GTK_IS_EDITABLE (focused_widget)) {
3280                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3281                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3282                 gtk_clipboard_store (clipboard);
3283         } else if (GTK_IS_HTML (focused_widget)) {
3284                 gtk_html_copy (GTK_HTML (focused_widget));
3285                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3286                 gtk_clipboard_store (clipboard);
3287         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3288                 GtkTextBuffer *buffer;
3289                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3290                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3291                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3292                 gtk_clipboard_store (clipboard);
3293         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3294                 TnyList *header_list = modest_header_view_get_selected_headers (
3295                                 MODEST_HEADER_VIEW (focused_widget));
3296                 gboolean continue_download = FALSE;
3297                 gint num_of_unc_msgs;
3298
3299                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3300
3301                 if (num_of_unc_msgs) {
3302                         TnyAccount *account = get_account_from_header_list (header_list);
3303                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3304                         g_object_unref (account);
3305                 }
3306
3307                 if (num_of_unc_msgs == 0 || continue_download) {
3308                         modest_platform_information_banner (
3309                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3310                         modest_header_view_copy_selection (
3311                                         MODEST_HEADER_VIEW (focused_widget));
3312                 } else
3313                         copied = FALSE;
3314
3315                 g_object_unref (header_list);
3316
3317         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3318                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3319         }
3320
3321         /* Show information banner if there was a copy to clipboard */
3322         if(copied)
3323                 modest_platform_information_banner (
3324                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3325 }
3326
3327 void
3328 modest_ui_actions_on_undo (GtkAction *action,
3329                            ModestWindow *window)
3330 {
3331         ModestEmailClipboard *clipboard = NULL;
3332
3333         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3334                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3335         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3336                 /* Clear clipboard source */
3337                 clipboard = modest_runtime_get_email_clipboard ();
3338                 modest_email_clipboard_clear (clipboard);               
3339         }
3340         else {
3341                 g_return_if_reached ();
3342         }
3343 }
3344
3345 void
3346 modest_ui_actions_on_redo (GtkAction *action,
3347                            ModestWindow *window)
3348 {
3349         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3350                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3351         }
3352         else {
3353                 g_return_if_reached ();
3354         }
3355 }
3356
3357
3358 static void
3359 destroy_information_note (ModestMailOperation *mail_op, 
3360                           gpointer user_data)
3361 {
3362         /* destroy information note */
3363         gtk_widget_destroy (GTK_WIDGET(user_data));
3364 }
3365
3366 static void
3367 destroy_folder_information_note (ModestMailOperation *mail_op, 
3368                                  TnyFolder *new_folder,
3369                                  gpointer user_data)
3370 {
3371         /* destroy information note */
3372         gtk_widget_destroy (GTK_WIDGET(user_data));
3373 }
3374
3375
3376 static void
3377 paste_as_attachment_free (gpointer data)
3378 {
3379         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3380
3381         gtk_widget_destroy (helper->banner);
3382         g_object_unref (helper->banner);
3383         g_free (helper);
3384 }
3385
3386 static void
3387 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3388                             TnyHeader *header,
3389                             TnyMsg *msg,
3390                             gpointer userdata)
3391 {
3392         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3393         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3394
3395         if (msg == NULL)
3396                 return;
3397
3398         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3399         
3400 }
3401
3402 void
3403 modest_ui_actions_on_paste (GtkAction *action,
3404                             ModestWindow *window)
3405 {
3406         GtkWidget *focused_widget = NULL;
3407         GtkWidget *inf_note = NULL;
3408         ModestMailOperation *mail_op = NULL;
3409
3410         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3411         if (GTK_IS_EDITABLE (focused_widget)) {
3412                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3413         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3414                 ModestEmailClipboard *e_clipboard = NULL;
3415                 e_clipboard = modest_runtime_get_email_clipboard ();
3416                 if (modest_email_clipboard_cleared (e_clipboard)) {
3417                         GtkTextBuffer *buffer;
3418                         GtkClipboard *clipboard;
3419
3420                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3421                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3422                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3423                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3424                         ModestMailOperation *mail_op;
3425                         TnyFolder *src_folder;
3426                         TnyList *data;
3427                         gboolean delete;
3428                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3429                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3430                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3431                                                                            _CS("ckct_nw_pasting"));
3432                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3433                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3434                         if (helper->banner != NULL) {
3435                                 g_object_ref (G_OBJECT (helper->banner));
3436                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3437                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3438                         }
3439
3440                         if (data != NULL) {
3441                                 modest_mail_operation_get_msgs_full (mail_op, 
3442                                                                      data,
3443                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3444                                                                      helper,
3445                                                                      paste_as_attachment_free);
3446                         }
3447                 }
3448         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3449                 ModestEmailClipboard *clipboard = NULL;
3450                 TnyFolder *src_folder = NULL;
3451                 TnyFolderStore *folder_store = NULL;
3452                 TnyList *data = NULL;           
3453                 gboolean delete = FALSE;
3454                 
3455                 /* Check clipboard source */
3456                 clipboard = modest_runtime_get_email_clipboard ();
3457                 if (modest_email_clipboard_cleared (clipboard)) 
3458                         return;
3459                 
3460                 /* Get elements to paste */
3461                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3462
3463                 /* Create a new mail operation */
3464                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3465                 
3466                 /* Get destination folder */
3467                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3468
3469                 /* transfer messages  */
3470                 if (data != NULL) {
3471                         gint response = 0;
3472
3473                         /* Ask for user confirmation */
3474                         response = 
3475                                 modest_ui_actions_msgs_move_to_confirmation (window, 
3476                                                                              TNY_FOLDER (folder_store), 
3477                                                                              delete,
3478                                                                              data);
3479                         
3480                         if (response == GTK_RESPONSE_OK) {
3481                                 /* Launch notification */
3482                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3483                                                                              _CS("ckct_nw_pasting"));
3484                                 if (inf_note != NULL)  {
3485                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3486                                         gtk_widget_show (GTK_WIDGET(inf_note));
3487                                 }
3488
3489                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3490                                 modest_mail_operation_xfer_msgs (mail_op, 
3491                                                                  data,
3492                                                                  TNY_FOLDER (folder_store),
3493                                                                  delete,
3494                                                                  destroy_information_note,
3495                                                                  inf_note);                             
3496                         } else {
3497                                 g_object_unref (mail_op);
3498                         }
3499                         
3500                 } else if (src_folder != NULL) {                        
3501                         /* Launch notification */
3502                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3503                                                                      _CS("ckct_nw_pasting"));
3504                         if (inf_note != NULL)  {
3505                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3506                                 gtk_widget_show (GTK_WIDGET(inf_note));
3507                         }
3508                         
3509                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3510                         modest_mail_operation_xfer_folder (mail_op, 
3511                                                            src_folder,
3512                                                            folder_store,
3513                                                            delete,
3514                                                            destroy_folder_information_note,
3515                                                            inf_note);
3516                 }
3517
3518                 /* Free */
3519                 if (data != NULL) 
3520                         g_object_unref (data);
3521                 if (src_folder != NULL) 
3522                         g_object_unref (src_folder);
3523                 if (folder_store != NULL) 
3524                         g_object_unref (folder_store);
3525         }
3526 }
3527
3528
3529 void
3530 modest_ui_actions_on_select_all (GtkAction *action,
3531                                  ModestWindow *window)
3532 {
3533         GtkWidget *focused_widget;
3534
3535         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3536         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3537                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3538         } else if (GTK_IS_LABEL (focused_widget)) {
3539                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3540         } else if (GTK_IS_EDITABLE (focused_widget)) {
3541                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3542         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3543                 GtkTextBuffer *buffer;
3544                 GtkTextIter start, end;
3545
3546                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3547                 gtk_text_buffer_get_start_iter (buffer, &start);
3548                 gtk_text_buffer_get_end_iter (buffer, &end);
3549                 gtk_text_buffer_select_range (buffer, &start, &end);
3550         } else if (GTK_IS_HTML (focused_widget)) {
3551                 gtk_html_select_all (GTK_HTML (focused_widget));
3552         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3553                 GtkWidget *header_view = focused_widget;
3554                 GtkTreeSelection *selection = NULL;
3555                 
3556                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3557                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3558                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3559                 }
3560                                 
3561                 /* Disable window dimming management */
3562                 modest_window_disable_dimming (MODEST_WINDOW(window));
3563                 
3564                 /* Select all messages */
3565                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3566                 gtk_tree_selection_select_all (selection);
3567
3568                 /* Set focuse on header view */
3569                 gtk_widget_grab_focus (header_view);
3570
3571
3572                 /* Enable window dimming management */
3573                 modest_window_enable_dimming (MODEST_WINDOW(window));
3574                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3575         }
3576
3577 }
3578
3579 void
3580 modest_ui_actions_on_mark_as_read (GtkAction *action,
3581                                    ModestWindow *window)
3582 {       
3583         g_return_if_fail (MODEST_IS_WINDOW(window));
3584                 
3585         /* Mark each header as read */
3586         do_headers_action (window, headers_action_mark_as_read, NULL);
3587 }
3588
3589 void
3590 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3591                                      ModestWindow *window)
3592 {       
3593         g_return_if_fail (MODEST_IS_WINDOW(window));
3594                 
3595         /* Mark each header as read */
3596         do_headers_action (window, headers_action_mark_as_unread, NULL);
3597 }
3598
3599 void
3600 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3601                                   GtkRadioAction *selected,
3602                                   ModestWindow *window)
3603 {
3604         gint value;
3605
3606         value = gtk_radio_action_get_current_value (selected);
3607         if (MODEST_IS_WINDOW (window)) {
3608                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3609         }
3610 }
3611
3612 void
3613 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3614                                                GtkRadioAction *selected,
3615                                                ModestWindow *window)
3616 {
3617         TnyHeaderFlags flags;
3618         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3619
3620         flags = gtk_radio_action_get_current_value (selected);
3621         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3622 }
3623
3624 void
3625 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3626                                                   GtkRadioAction *selected,
3627                                                   ModestWindow *window)
3628 {
3629         gint file_format;
3630
3631         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3632
3633         file_format = gtk_radio_action_get_current_value (selected);
3634         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3635 }
3636
3637
3638 void
3639 modest_ui_actions_on_zoom_plus (GtkAction *action,
3640                                 ModestWindow *window)
3641 {
3642         g_return_if_fail (MODEST_IS_WINDOW (window));
3643
3644         modest_window_zoom_plus (MODEST_WINDOW (window));
3645 }
3646
3647 void     
3648 modest_ui_actions_on_zoom_minus (GtkAction *action,
3649                                  ModestWindow *window)
3650 {
3651         g_return_if_fail (MODEST_IS_WINDOW (window));
3652
3653         modest_window_zoom_minus (MODEST_WINDOW (window));
3654 }
3655
3656 void     
3657 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3658                                            ModestWindow *window)
3659 {
3660         ModestWindowMgr *mgr;
3661         gboolean fullscreen, active;
3662         g_return_if_fail (MODEST_IS_WINDOW (window));
3663
3664         mgr = modest_runtime_get_window_mgr ();
3665
3666         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3667         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3668
3669         if (active != fullscreen) {
3670                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3671                 gtk_window_present (GTK_WINDOW (window));
3672         }
3673 }
3674
3675 void
3676 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3677                                         ModestWindow *window)
3678 {
3679         ModestWindowMgr *mgr;
3680         gboolean fullscreen;
3681
3682         g_return_if_fail (MODEST_IS_WINDOW (window));
3683
3684         mgr = modest_runtime_get_window_mgr ();
3685         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3686         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3687
3688         gtk_window_present (GTK_WINDOW (window));
3689 }
3690
3691 /* 
3692  * Used by modest_ui_actions_on_details to call do_headers_action 
3693  */
3694 static void
3695 headers_action_show_details (TnyHeader *header, 
3696                              ModestWindow *window,
3697                              gpointer user_data)
3698
3699 {
3700         GtkWidget *dialog;
3701         
3702         /* Create dialog */
3703         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3704
3705         /* Run dialog */
3706         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3707         gtk_widget_show_all (dialog);
3708         gtk_dialog_run (GTK_DIALOG (dialog));
3709
3710         gtk_widget_destroy (dialog);
3711 }
3712
3713 /*
3714  * Show the folder details in a ModestDetailsDialog widget
3715  */
3716 static void
3717 show_folder_details (TnyFolder *folder, 
3718                      GtkWindow *window)
3719 {
3720         GtkWidget *dialog;
3721         
3722         /* Create dialog */
3723         dialog = modest_details_dialog_new_with_folder (window, folder);
3724
3725         /* Run dialog */
3726         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3727         gtk_widget_show_all (dialog);
3728         gtk_dialog_run (GTK_DIALOG (dialog));
3729
3730         gtk_widget_destroy (dialog);
3731 }
3732
3733 /*
3734  * Show the header details in a ModestDetailsDialog widget
3735  */
3736 void     
3737 modest_ui_actions_on_details (GtkAction *action, 
3738                               ModestWindow *win)
3739 {
3740         TnyList * headers_list;
3741         TnyIterator *iter;
3742         TnyHeader *header;              
3743
3744         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3745                 TnyMsg *msg;
3746
3747                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3748                 if (!msg)
3749                         return;
3750                 g_object_unref (msg);           
3751
3752                 headers_list = get_selected_headers (win);
3753                 if (!headers_list)
3754                         return;
3755
3756                 iter = tny_list_create_iterator (headers_list);
3757
3758                 header = TNY_HEADER (tny_iterator_get_current (iter));
3759                 if (header) {
3760                         headers_action_show_details (header, win, NULL);
3761                         g_object_unref (header);
3762                 }
3763
3764                 g_object_unref (iter);
3765                 g_object_unref (headers_list);
3766
3767         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3768                 GtkWidget *folder_view, *header_view;
3769
3770                 /* Check which widget has the focus */
3771                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3772                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3773                 if (gtk_widget_is_focus (folder_view)) {
3774                         TnyFolderStore *folder_store
3775                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3776                         if (!folder_store) {
3777                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3778                                 return; 
3779                         }
3780                         /* Show only when it's a folder */
3781                         /* This function should not be called for account items, 
3782                          * because we dim the menu item for them. */
3783                         if (TNY_IS_FOLDER (folder_store)) {
3784                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3785                         }
3786
3787                         g_object_unref (folder_store);
3788
3789                 } else {
3790                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3791                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3792                         /* Show details of each header */
3793                         do_headers_action (win, headers_action_show_details, header_view);
3794                 }
3795         }
3796 }
3797
3798 void     
3799 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3800                                      ModestMsgEditWindow *window)
3801 {
3802         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3803
3804         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3805 }
3806
3807 void     
3808 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3809                                       ModestMsgEditWindow *window)
3810 {
3811         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3812
3813         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3814 }
3815
3816 void
3817 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3818                                        ModestMainWindow *main_window)
3819 {
3820         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3821
3822         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3823                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3824         else
3825                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3826 }
3827
3828 void 
3829 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3830                                      ModestWindow *window)
3831 {
3832         gboolean active, fullscreen = FALSE;
3833         ModestWindowMgr *mgr;
3834
3835         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3836
3837         /* Check if we want to toggle the toolbar vuew in fullscreen
3838            or normal mode */
3839         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3840                      "ViewShowToolbarFullScreen")) {
3841                 fullscreen = TRUE;
3842         }
3843
3844         /* Toggle toolbar */
3845         mgr = modest_runtime_get_window_mgr ();
3846         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3847 }
3848
3849 void     
3850 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3851                                            ModestMsgEditWindow *window)
3852 {
3853         modest_msg_edit_window_select_font (window);
3854 }
3855
3856
3857 void
3858 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3859                                                   const gchar *display_name,
3860                                                   GtkWindow *window)
3861 {
3862         /* don't update the display name if it was already set;
3863          * updating the display name apparently is expensive */
3864         const gchar* old_name = gtk_window_get_title (window);
3865
3866         if (display_name == NULL)
3867                 display_name = " ";
3868
3869         if (old_name && display_name && strcmp (old_name, display_name) == 0)
3870                 return; /* don't do anything */
3871
3872         /* This is usually used to change the title of the main window, which
3873          * is the one that holds the folder view. Note that this change can
3874          * happen even when the widget doesn't have the focus. */
3875         gtk_window_set_title (window, display_name);
3876
3877 }
3878
3879 void
3880 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3881 {
3882         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3883         modest_msg_edit_window_select_contacts (window);
3884 }
3885
3886 void
3887 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3888 {
3889         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3890         modest_msg_edit_window_check_names (window, FALSE);
3891 }
3892
3893 static void
3894 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3895 {
3896         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3897                                          GTK_WIDGET (user_data));
3898 }
3899
3900 /*
3901  * This function is used to track changes in the selection of the
3902  * folder view that is inside the "move to" dialog to enable/disable
3903  * the OK button because we do not want the user to select a disallowed
3904  * destination for a folder.
3905  * The user also not desired to be able to use NEW button on items where
3906  * folder creation is not possibel.
3907  */
3908 static void
3909 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3910                                             TnyFolderStore *folder_store,
3911                                             gboolean selected,
3912                                             gpointer user_data)
3913 {
3914         GtkWidget *dialog = NULL;
3915         GtkWidget *ok_button = NULL, *new_button = NULL;
3916         GList *children = NULL;
3917         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3918         gboolean moving_folder = FALSE;
3919         gboolean is_local_account = TRUE;
3920         GtkWidget *folder_view = NULL;
3921         ModestTnyFolderRules rules;
3922
3923         if (!selected)
3924                 return;
3925
3926         /* Get the OK button */
3927         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3928         if (!dialog)
3929                 return;
3930
3931         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3932         ok_button = GTK_WIDGET (children->next->next->data);
3933         new_button = GTK_WIDGET (children->next->data);
3934         g_list_free (children);
3935
3936         /* check if folder_store is an remote account */
3937         if (TNY_IS_ACCOUNT (folder_store)) {
3938                 TnyAccount *local_account = NULL;
3939                 TnyAccount *mmc_account = NULL;
3940                 ModestTnyAccountStore *account_store = NULL;
3941
3942                 account_store = modest_runtime_get_account_store ();
3943                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3944                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
3945
3946                 if ((gpointer) local_account != (gpointer) folder_store &&
3947                     (gpointer) mmc_account != (gpointer) folder_store) {
3948                         is_local_account = FALSE;
3949                         /* New button should be dimmed on remote
3950                            account root */
3951                         new_sensitive = FALSE;
3952                 }
3953                 g_object_unref (local_account);
3954         }
3955
3956         /* Check the target folder rules */
3957         if (TNY_IS_FOLDER (folder_store)) {
3958                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3959                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3960                         ok_sensitive = FALSE;
3961                         new_sensitive = FALSE;
3962                         goto end;
3963                 }
3964         }
3965
3966         /* Check if we're moving a folder */
3967         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3968                 /* Get the widgets */
3969                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3970                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3971                 if (gtk_widget_is_focus (folder_view))
3972                         moving_folder = TRUE;
3973         }
3974
3975         if (moving_folder) {
3976                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3977
3978                 /* Get the folder to move */
3979                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3980                 
3981                 /* Check that we're not moving to the same folder */
3982                 if (TNY_IS_FOLDER (moved_folder)) {
3983                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3984                         if (parent == folder_store)
3985                                 ok_sensitive = FALSE;
3986                         g_object_unref (parent);
3987                 } 
3988
3989                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3990                         /* Do not allow to move to an account unless it's the
3991                            local folders account */
3992                         if (!is_local_account)
3993                                 ok_sensitive = FALSE;
3994                 } 
3995
3996                 if (ok_sensitive && (moved_folder == folder_store)) {
3997                         /* Do not allow to move to itself */
3998                         ok_sensitive = FALSE;
3999                 }
4000                 g_object_unref (moved_folder);
4001         } else {
4002                 TnyHeader *header = NULL;
4003                 TnyFolder *src_folder = NULL;
4004
4005                 /* Moving a message */
4006                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4007                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
4008                         src_folder = tny_header_get_folder (header);
4009                         g_object_unref (header);
4010                 } else {
4011                         src_folder = 
4012                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
4013                 }
4014
4015                 /* Do not allow to move the msg to the same folder */
4016                 /* Do not allow to move the msg to an account */
4017                 if ((gpointer) src_folder == (gpointer) folder_store ||
4018                     TNY_IS_ACCOUNT (folder_store))
4019                         ok_sensitive = FALSE;
4020                 g_object_unref (src_folder);
4021         }
4022
4023  end:
4024         /* Set sensitivity of the OK button */
4025         gtk_widget_set_sensitive (ok_button, ok_sensitive);
4026         /* Set sensitivity of the NEW button */
4027         gtk_widget_set_sensitive (new_button, new_sensitive);
4028 }
4029
4030
4031 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4032
4033 static GtkWidget*
4034 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4035 {
4036         return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4037                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4038 }
4039
4040 static GtkWidget*
4041 create_move_to_dialog (GtkWindow *win,
4042                        GtkWidget *folder_view,
4043                        GtkWidget **tree_view)
4044 {
4045         GtkWidget *dialog, *scroll;
4046         GtkWidget *new_button;
4047
4048         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4049                                               GTK_WINDOW (win),
4050                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4051                                               NULL);
4052
4053         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4054         /* We do this manually so GTK+ does not associate a response ID for
4055          * the button. */
4056         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4057         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4058         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4059
4060         /* Create scrolled window */
4061         scroll = gtk_scrolled_window_new (NULL, NULL);
4062         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
4063                                          GTK_POLICY_AUTOMATIC,
4064                                          GTK_POLICY_AUTOMATIC);
4065
4066         /* Create folder view */
4067         *tree_view = modest_platform_create_folder_view (NULL);
4068
4069         /* Track changes in the selection to
4070          * disable the OK button whenever "Move to" is not possible
4071          * disbale NEW button whenever New is not possible */
4072         g_signal_connect (*tree_view,
4073                           "folder_selection_changed",
4074                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4075                           win);
4076
4077         /* Listen to clicks on New button */
4078         g_signal_connect (G_OBJECT (new_button), 
4079                           "clicked", 
4080                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
4081                           *tree_view);
4082
4083         /* It could happen that we're trying to move a message from a
4084            window (msg window for example) after the main window was
4085            closed, so we can not just get the model of the folder
4086            view */
4087         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4088                 const gchar *visible_id = NULL;
4089
4090                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4091                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4092                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
4093                                                MODEST_FOLDER_VIEW(*tree_view));
4094
4095                 visible_id = 
4096                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4097
4098                 /* Show the same account than the one that is shown in the main window */
4099                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
4100                                                                              visible_id);
4101         } else {
4102                 const gchar *active_account_name = NULL;
4103                 ModestAccountMgr *mgr = NULL;
4104                 ModestAccountSettings *settings = NULL;
4105                 ModestServerAccountSettings *store_settings = NULL;
4106
4107                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4108                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4109                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4110                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4111
4112                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4113                 mgr = modest_runtime_get_account_mgr ();
4114                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4115
4116                 if (settings) {
4117                         const gchar *store_account_name;
4118                         store_settings = modest_account_settings_get_store_settings (settings);
4119                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4120
4121                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4122                                                                                      store_account_name);
4123                         g_object_unref (store_settings);
4124                         g_object_unref (settings);
4125                 }
4126         }
4127
4128         /* we keep a pointer to the embedded folder view, so we can retrieve it with
4129          *   get_folder_view_from_move_to_dialog 
4130          * (see above) later (needed for focus handling) 
4131          */
4132         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4133
4134         
4135         /* Hide special folders */
4136         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4137
4138         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4139
4140         /* Add scroll to dialog */
4141         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4142                             scroll, TRUE, TRUE, 0);
4143
4144         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4145         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4146
4147         return dialog;
4148 }
4149
4150 /*
4151  * Returns TRUE if at least one of the headers of the list belongs to
4152  * a message that has been fully retrieved.
4153  */
4154 #if 0 /* no longer in use. delete in 2007.10 */
4155 static gboolean
4156 has_retrieved_msgs (TnyList *list)
4157 {
4158         TnyIterator *iter;
4159         gboolean found = FALSE;
4160
4161         iter = tny_list_create_iterator (list);
4162         while (!tny_iterator_is_done (iter) && !found) {
4163                 TnyHeader *header;
4164                 TnyHeaderFlags flags = 0;
4165
4166                 header = TNY_HEADER (tny_iterator_get_current (iter));
4167                 if (header) {
4168                         flags = tny_header_get_flags (header);
4169                         if (flags & TNY_HEADER_FLAG_CACHED)
4170 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
4171                                 found = TRUE;
4172
4173                         g_object_unref (header);
4174                 }
4175
4176                 if (!found)
4177                         tny_iterator_next (iter);
4178         }
4179         g_object_unref (iter);
4180
4181         return found;
4182 }
4183 #endif /* 0 */
4184
4185
4186 /*
4187  * Shows a confirmation dialog to the user when we're moving messages
4188  * from a remote server to the local storage. Returns the dialog
4189  * response. If it's other kind of movement then it always returns
4190  * GTK_RESPONSE_OK
4191  *
4192  * This one is used by the next functions:
4193  *      modest_ui_actions_on_paste                      - commented out
4194  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4195  */
4196 gint
4197 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4198                                              TnyFolder *dest_folder,
4199                                              gboolean delete,
4200                                              TnyList *headers)
4201 {
4202         gint response = GTK_RESPONSE_OK;
4203         TnyAccount *account = NULL;
4204         TnyFolder *src_folder = NULL;
4205         TnyIterator *iter = NULL;
4206         TnyHeader *header = NULL;
4207
4208         /* return with OK if the destination is a remote folder */
4209         if (modest_tny_folder_is_remote_folder (dest_folder))
4210                 return GTK_RESPONSE_OK;
4211
4212         /* Get source folder */
4213         iter = tny_list_create_iterator (headers);
4214         header = TNY_HEADER (tny_iterator_get_current (iter));
4215         if (header) {
4216                 src_folder = tny_header_get_folder (header);
4217                 g_object_unref (header);
4218         }
4219         g_object_unref (iter);
4220
4221         /* if no src_folder, message may be an attahcment */
4222         if (src_folder == NULL) 
4223                 return GTK_RESPONSE_CANCEL;
4224
4225         /* If the source is a local or MMC folder */
4226         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4227                 g_object_unref (src_folder);
4228                 return GTK_RESPONSE_OK;
4229         }
4230
4231         /* Get the account */
4232         account = tny_folder_get_account (src_folder);
4233
4234         /* now if offline we ask the user */
4235         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4236                 response = GTK_RESPONSE_OK;
4237         else
4238                 response = GTK_RESPONSE_CANCEL;
4239
4240         /* Frees */
4241         g_object_unref (src_folder);
4242         g_object_unref (account);
4243
4244         return response;
4245 }
4246
4247 static void
4248 move_to_cb (ModestMailOperation *mail_op, 
4249             gpointer user_data)
4250 {
4251         MoveToHelper *helper = (MoveToHelper *) user_data;
4252
4253         /* Note that the operation could have failed, in that case do
4254            nothing */
4255         if (modest_mail_operation_get_status (mail_op) == 
4256             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4257
4258                 GObject *object = modest_mail_operation_get_source (mail_op);
4259                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4260                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4261
4262                         if (!modest_msg_view_window_select_next_message (self))
4263                                 if (!modest_msg_view_window_select_previous_message (self))
4264                                         /* No more messages to view, so close this window */
4265                                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4266                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4267                         GtkWidget *header_view;
4268                         GtkTreePath *path;
4269                         GtkTreeSelection *sel;
4270
4271                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4272                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4273                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4274                         path = gtk_tree_row_reference_get_path (helper->reference);
4275                         gtk_tree_selection_select_path (sel, path);
4276                         gtk_tree_path_free (path);
4277                 }
4278                 g_object_unref (object);
4279         }
4280
4281         /* Close the "Pasting" information banner */
4282         gtk_widget_destroy (GTK_WIDGET(helper->banner));
4283         if (helper->reference != NULL)
4284                 gtk_tree_row_reference_free (helper->reference);
4285         g_free (helper);
4286 }
4287
4288 static void
4289 folder_move_to_cb (ModestMailOperation *mail_op, 
4290                    TnyFolder *new_folder,
4291                    gpointer user_data)
4292 {
4293         move_to_cb (mail_op, user_data);
4294 }
4295
4296 static void
4297 msgs_move_to_cb (ModestMailOperation *mail_op, 
4298                  gpointer user_data)
4299 {
4300         move_to_cb (mail_op, user_data);
4301 }
4302
4303 void
4304 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4305                                              gpointer user_data)
4306 {
4307         ModestWindow *main_window = NULL;
4308         GObject *win = NULL;
4309         
4310         /* Disable next automatic folder selection */
4311         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4312                                                          FALSE); /* don't create */
4313         if (main_window) {
4314                 GtkWidget *folder_view = NULL;
4315         
4316                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4317                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4318                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4319                 
4320                 if (user_data && TNY_IS_FOLDER (user_data)) {
4321                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4322                                                           TNY_FOLDER (user_data), FALSE);
4323                 }
4324         }
4325
4326         /* Show notification dialog */
4327         win = modest_mail_operation_get_source (mail_op);
4328         modest_platform_run_information_dialog ((GtkWindow *) win, _("mail_in_ui_folder_move_target_error"));
4329         if (win)
4330                 g_object_unref (win);
4331 }
4332
4333 void
4334 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
4335                                               gpointer user_data)
4336 {
4337         GObject *win = modest_mail_operation_get_source (mail_op);
4338         const GError *error = modest_mail_operation_get_error (mail_op);
4339
4340         g_return_if_fail (error != NULL);
4341         if (error->message != NULL)             
4342                 g_printerr ("modest: %s\n", error->message);
4343         else
4344                 g_printerr ("modest: unkonw error on send&receive operation");
4345
4346         /* Show error message */
4347 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
4348 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4349 /*                                                      _CS("sfil_ib_unable_to_receive")); */
4350 /*      else  */
4351 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4352 /*                                                      _CS("sfil_ib_unable_to_send")); */
4353         g_object_unref (win);
4354 }
4355
4356 static void
4357 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4358                        TnyHeader *header, 
4359                        gboolean canceled,
4360                        TnyMsg *msg, 
4361                        GError *err,
4362                        gpointer user_data)
4363 {
4364         TnyList *parts;
4365         TnyIterator *iter;
4366         gint pending_purges = 0;
4367         gboolean some_purged = FALSE;
4368         ModestWindow *win = MODEST_WINDOW (user_data);
4369         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4370
4371         /* If there was any error */
4372         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4373                 modest_window_mgr_unregister_header (mgr, header);
4374                 return;
4375         }
4376
4377         /* Once the message has been retrieved for purging, we check if
4378          * it's all ok for purging */
4379
4380         parts = tny_simple_list_new ();
4381         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4382         iter = tny_list_create_iterator (parts);
4383
4384         while (!tny_iterator_is_done (iter)) {
4385                 TnyMimePart *part;
4386                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4387                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4388                         if (tny_mime_part_is_purged (part))
4389                                 some_purged = TRUE;
4390                         else
4391                                 pending_purges++;
4392                 }
4393
4394                 if (part)
4395                         g_object_unref (part);
4396
4397                 tny_iterator_next (iter);
4398         }
4399         g_object_unref (iter);
4400         
4401
4402         if (pending_purges>0) {
4403                 gint response;
4404                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4405
4406                 if (response == GTK_RESPONSE_OK) {
4407                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4408                         iter = tny_list_create_iterator (parts);
4409                         while (!tny_iterator_is_done (iter)) {
4410                                 TnyMimePart *part;
4411                                 
4412                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4413                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4414                                         tny_mime_part_set_purged (part);
4415
4416                                 if (part)
4417                                         g_object_unref (part);
4418
4419                                 tny_iterator_next (iter);
4420                         }
4421                         
4422                         tny_msg_rewrite_cache (msg);
4423                 }
4424      /* } else { */
4425                 /* This string no longer exists, refer to NB#75415 for more info */
4426                 /* modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged")); */
4427         }
4428         g_object_unref (iter);
4429
4430         modest_window_mgr_unregister_header (mgr, header);
4431
4432         g_object_unref (parts);
4433 }
4434
4435 static void
4436 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4437                                                      ModestMainWindow *win)
4438 {
4439         GtkWidget *header_view;
4440         TnyList *header_list;
4441         TnyIterator *iter;
4442         TnyHeader *header;
4443         TnyHeaderFlags flags;
4444         ModestWindow *msg_view_window =  NULL;
4445         gboolean found;
4446
4447         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4448
4449         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4450                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4451
4452         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4453         if (!header_list) {
4454                 g_warning ("%s: no header selected", __FUNCTION__);
4455                 return;
4456         }
4457         
4458         if (tny_list_get_length (header_list) == 1) {
4459                 iter = tny_list_create_iterator (header_list);
4460                 header = TNY_HEADER (tny_iterator_get_current (iter));
4461                 g_object_unref (iter);
4462         } else
4463                 return;
4464         
4465         if (!header || !TNY_IS_HEADER(header)) {
4466                 g_warning ("%s: header is not valid", __FUNCTION__);
4467                 return;
4468         }
4469         
4470         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4471                                                           header, &msg_view_window);
4472         flags = tny_header_get_flags (header);
4473         if (!(flags & TNY_HEADER_FLAG_CACHED))
4474                 return;
4475         if (found) {
4476                 if (msg_view_window != NULL) 
4477                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4478                 else {
4479                         /* do nothing; uid was registered before, so window is probably on it's way */
4480                         g_warning ("debug: header %p has already been registered", header);
4481                 }
4482         } else {
4483                 ModestMailOperation *mail_op = NULL;
4484                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4485                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4486                                                                          modest_ui_actions_get_msgs_full_error_handler,
4487                                                                          NULL, NULL);
4488                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4489                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4490                 
4491                 g_object_unref (mail_op);
4492         }
4493         if (header)
4494                 g_object_unref (header);
4495         if (header_list)
4496                 g_object_unref (header_list);
4497 }
4498
4499 /**
4500  * Utility function that transfer messages from both the main window
4501  * and the msg view window when using the "Move to" dialog
4502  */
4503 static void
4504 xfer_messages_from_move_to_cb  (gboolean canceled, GError *err,
4505                                 GtkWindow *parent_window, 
4506                                 TnyAccount *account, gpointer user_data)
4507 {
4508         TnyFolderStore *dst_folder = TNY_FOLDER_STORE (user_data);
4509         ModestWindow *win = MODEST_WINDOW (parent_window);
4510         TnyList *headers = NULL;
4511         TnyAccount *dst_account = NULL;
4512         const gchar *proto_str = NULL;
4513         gboolean dst_is_pop = FALSE;
4514
4515         if (canceled || err) {
4516                 g_object_unref (dst_folder);
4517                 return;
4518         }
4519
4520         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4521         proto_str = tny_account_get_proto (dst_account);
4522
4523         /* tinymail will return NULL for local folders it seems */
4524         dst_is_pop = proto_str &&
4525                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4526                  MODEST_PROTOCOL_STORE_POP);
4527
4528         g_object_unref (dst_account);
4529
4530         /* Get selected headers */
4531         headers = get_selected_headers (MODEST_WINDOW (win));
4532         if (!headers) {
4533                 g_warning ("%s: no headers selected", __FUNCTION__);
4534                 return;
4535         }
4536
4537
4538         if (dst_is_pop) {
4539                 modest_platform_information_banner (GTK_WIDGET (win),
4540                                                     NULL,
4541                                                     ngettext("mail_in_ui_folder_move_target_error",
4542                                                              "mail_in_ui_folder_move_targets_error",
4543                                                              tny_list_get_length (headers)));
4544                 g_object_unref (headers);
4545                 return;
4546         }
4547
4548         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4549         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4550                                                            _CS("ckct_nw_pasting"));
4551         if (helper->banner != NULL)  {
4552                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4553                 gtk_widget_show (GTK_WIDGET(helper->banner));
4554         }
4555
4556         if (MODEST_IS_MAIN_WINDOW (win)) {
4557                 GtkWidget *header_view = 
4558                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4559                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4560                 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4561         }
4562
4563         ModestMailOperation *mail_op = 
4564                 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4565                                                                modest_ui_actions_move_folder_error_handler,
4566                                                                NULL, NULL);
4567         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4568                                          mail_op);
4569
4570         modest_mail_operation_xfer_msgs (mail_op, 
4571                                          headers,
4572                                          TNY_FOLDER (dst_folder),
4573                                          TRUE,
4574                                          msgs_move_to_cb,
4575                                          helper);
4576
4577         g_object_unref (G_OBJECT (mail_op));
4578         g_object_unref (headers);
4579         g_object_unref (dst_folder);
4580 }
4581
4582 typedef struct {
4583         TnyAccount *dst_account;
4584         ModestConnectedPerformer callback;
4585         gpointer data;
4586 } DoubleConnectionInfo;
4587
4588 static void
4589 src_account_connect_performer (gboolean canceled, 
4590                                GError *err,
4591                                GtkWindow *parent_window, 
4592                                TnyAccount *src_account, 
4593                                gpointer user_data)
4594 {
4595         DoubleConnectionInfo *info = (DoubleConnectionInfo *) user_data;
4596
4597         if (canceled || err) {
4598                 /* If there was any error call the user callback */
4599                 info->callback (canceled, err, parent_window, src_account, info->data);
4600         } else {
4601                 /* Connect the destination account */
4602                 modest_platform_connect_if_remote_and_perform (parent_window, TRUE, 
4603                                                                TNY_FOLDER_STORE (info->dst_account),
4604                                                                info->callback, info->data);
4605         }
4606
4607         /* Free the info object */
4608         g_object_unref (info->dst_account);
4609         g_slice_free (DoubleConnectionInfo, info);
4610 }
4611
4612 typedef struct {
4613         TnyFolder *src_folder;
4614         TnyFolderStore *dst_folder;
4615         gboolean delete_original;
4616         GtkWidget *folder_view;
4617 } MoveFolderInfo;
4618
4619 static void
4620 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
4621                 TnyAccount *account, gpointer user_data)
4622 {
4623         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
4624         GtkTreeSelection *sel;
4625         ModestMailOperation *mail_op = NULL;
4626         
4627         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
4628                 g_object_unref (G_OBJECT (info->src_folder));
4629                 g_object_unref (G_OBJECT (info->dst_folder));
4630                 g_free (info);
4631                 return;
4632         }
4633         
4634         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4635         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
4636                         _CS("ckct_nw_pasting"));
4637         if (helper->banner != NULL)  {
4638                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4639                 gtk_widget_show (GTK_WIDGET(helper->banner));
4640         }
4641         /* Clean folder on header view before moving it */
4642         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
4643         gtk_tree_selection_unselect_all (sel);
4644
4645         /* Let gtk events run. We need that the folder
4646            view frees its reference to the source
4647            folder *before* issuing the mail operation
4648            so we need the signal handler of selection
4649            changed to happen before the mail
4650            operation 
4651         while (gtk_events_pending ())
4652                 gtk_main_iteration ();   */
4653
4654         mail_op =
4655                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
4656                                 modest_ui_actions_move_folder_error_handler,
4657                                 info->src_folder, NULL);
4658         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4659                         mail_op);
4660
4661         /* Select *after* the changes */
4662         /* TODO: this function hangs UI after transfer */ 
4663         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4664         /*                                                        TNY_FOLDER (src_folder), TRUE); */
4665
4666         modest_mail_operation_xfer_folder (mail_op,
4667                         TNY_FOLDER (info->src_folder),
4668                         info->dst_folder,
4669                         info->delete_original, 
4670                         folder_move_to_cb, 
4671                         helper);
4672
4673         if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {       
4674                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
4675                                                   TNY_FOLDER (info->dst_folder), TRUE);
4676         }
4677         
4678         /* Unref mail operation */
4679         g_object_unref (G_OBJECT (mail_op));
4680         g_object_unref (G_OBJECT (info->src_folder));
4681         g_object_unref (G_OBJECT (info->dst_folder));
4682         g_free (user_data);
4683 }
4684
4685 /*
4686  * UI handler for the "Move to" action when invoked from the
4687  * ModestMainWindow
4688  */
4689 static void 
4690 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4691                                           GtkWidget *folder_view,
4692                                           TnyFolderStore *dst_folder,
4693                                           ModestMainWindow *win)
4694 {
4695         ModestHeaderView *header_view = NULL;
4696         TnyFolderStore *src_folder;
4697         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4698
4699         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4700
4701         /* Get the source folder */
4702         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4703
4704         /* Get header view */
4705         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4706
4707         /* Get folder or messages to transfer */
4708         if (gtk_widget_is_focus (folder_view)) {
4709                 gboolean do_xfer = TRUE;
4710
4711                 /* Allow only to transfer folders to the local root folder */
4712                 if (TNY_IS_ACCOUNT (dst_folder) && 
4713                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4714                         do_xfer = FALSE;
4715                 } else if (!TNY_IS_FOLDER (src_folder)) {
4716                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4717                         do_xfer = FALSE;
4718                 } /* else if (!online && modest_tny_folder_store_is_remote(src_folder)) {
4719                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER (src_folder));
4720                         TnyAccount *account = tny_folder_get_account (TNY_FOLDER (src_folder));
4721                         if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4722                                 do_xfer = FALSE;
4723                         g_object_unref (account);
4724                 }*/
4725
4726                 if (do_xfer) {
4727                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
4728                         info->src_folder = TNY_FOLDER (src_folder);
4729                         info->dst_folder = dst_folder;
4730                         info->delete_original = TRUE;
4731                         info->folder_view = folder_view;
4732                         g_object_ref (G_OBJECT (info->src_folder));
4733                         g_object_ref (G_OBJECT (info->dst_folder));
4734                         modest_platform_connect_if_remote_and_perform(GTK_WINDOW (win), TRUE,
4735                                     TNY_FOLDER_STORE (dst_folder), on_move_folder_cb, info);
4736                 }
4737         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4738                 gboolean do_xfer = TRUE;
4739
4740                 /* Show an error when trying to move msgs to an account */      
4741                 if (!TNY_IS_FOLDER (dst_folder)) {
4742                         modest_platform_information_banner (GTK_WIDGET (win),
4743                                                             NULL,
4744                                                             _CS("ckdg_ib_unable_to_move_to_current_location"));
4745                         goto free;
4746                 }
4747
4748                 /* Ask for confirmation if the source folder is remote and we're not connected */
4749                 if (!online && modest_tny_folder_store_is_remote(src_folder)) {
4750                         TnyList *headers = modest_header_view_get_selected_headers(header_view);
4751                         if (!msgs_already_deleted_from_server(headers, src_folder)) {
4752                                 guint num_headers = tny_list_get_length(headers);
4753                                 TnyAccount *account = get_account_from_header_list (headers);
4754                                 GtkResponseType response;
4755
4756                                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
4757                                                                                     ngettext("mcen_nc_get_msg",
4758                                                                                              "mcen_nc_get_msgs",
4759                                                                                              num_headers));
4760                                 if (response == GTK_RESPONSE_CANCEL)
4761                                         do_xfer = FALSE;
4762                                 
4763                                 g_object_unref (account);
4764                         }
4765                         g_object_unref(headers);
4766                 }
4767                 if (do_xfer) /* Transfer messages */ {
4768                         DoubleConnectionInfo *info = g_slice_new (DoubleConnectionInfo);
4769                         info->callback = xfer_messages_from_move_to_cb;
4770                         info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4771                         info->data = g_object_ref (dst_folder);
4772
4773                         modest_platform_connect_if_remote_and_perform(GTK_WINDOW (win), TRUE,
4774                                                                       TNY_FOLDER_STORE (src_folder), 
4775                                                                       src_account_connect_performer, 
4776                                                                       info);
4777                 }
4778         }
4779
4780  free:
4781         if (src_folder)
4782                 g_object_unref (src_folder);
4783 }
4784
4785
4786 /*
4787  * UI handler for the "Move to" action when invoked from the
4788  * ModestMsgViewWindow
4789  */
4790 static void 
4791 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4792                                               TnyFolderStore *dst_folder,
4793                                               ModestMsgViewWindow *win)
4794 {
4795         TnyHeader *header = NULL;
4796         TnyFolder *src_folder = NULL;
4797         TnyAccount *account = NULL;
4798         gboolean do_xfer = FALSE;
4799
4800         /* Create header list */
4801         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4802         src_folder = TNY_FOLDER (tny_header_get_folder(header));
4803         g_object_unref (header);
4804
4805         account = tny_folder_get_account (src_folder);
4806         if (!modest_tny_folder_store_is_remote(TNY_FOLDER_STORE(src_folder))) {
4807                 /* Transfer if the source folder is local */
4808                 do_xfer = TRUE;
4809         } else if (remote_folder_is_pop(TNY_FOLDER_STORE(src_folder))) {
4810                 /* Transfer if the source folder is POP (as it means
4811                  * that the message is already downloaded) */
4812                 do_xfer = TRUE;
4813         } else if (connect_to_get_msg(MODEST_WINDOW(win), 1, account)) {
4814                 /* Transfer after asking confirmation */
4815                 do_xfer = TRUE;
4816         }
4817
4818         if (do_xfer) {
4819                 g_object_ref (dst_folder);
4820                 modest_platform_connect_if_remote_and_perform(GTK_WINDOW (win), TRUE,
4821                                 TNY_FOLDER_STORE (dst_folder), xfer_messages_from_move_to_cb, dst_folder);
4822         }
4823         g_object_unref (account);
4824         g_object_unref (src_folder);
4825 }
4826
4827 void 
4828 modest_ui_actions_on_move_to (GtkAction *action, 
4829                               ModestWindow *win)
4830 {
4831         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4832         gint result = 0;
4833         TnyFolderStore *dst_folder = NULL;
4834         ModestMainWindow *main_window;
4835
4836         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4837                           MODEST_IS_MSG_VIEW_WINDOW (win));
4838
4839         /* Get the main window if exists */
4840         if (MODEST_IS_MAIN_WINDOW (win))
4841                 main_window = MODEST_MAIN_WINDOW (win);
4842         else
4843                 main_window = 
4844                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4845                                                                                FALSE)); /* don't create */
4846
4847         /* Get the folder view widget if exists */
4848         if (main_window)
4849                 folder_view = modest_main_window_get_child_widget (main_window,
4850                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4851         else
4852                 folder_view = NULL;
4853
4854         /* Create and run the dialog */
4855         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4856         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4857         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4858         result = gtk_dialog_run (GTK_DIALOG(dialog));
4859         g_object_ref (tree_view);
4860         gtk_widget_destroy (dialog);
4861
4862         if (result != GTK_RESPONSE_ACCEPT)
4863                 return;
4864
4865         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4866         /* Do window specific stuff */
4867         if (MODEST_IS_MAIN_WINDOW (win)) {
4868                 modest_ui_actions_on_main_window_move_to (action,
4869                                 folder_view,
4870                                 dst_folder,
4871                                 MODEST_MAIN_WINDOW (win));
4872         } else {
4873                 modest_ui_actions_on_msg_view_window_move_to (action,
4874                                 dst_folder,
4875                                 MODEST_MSG_VIEW_WINDOW (win));
4876         }
4877
4878         if (dst_folder)
4879                 g_object_unref (dst_folder);
4880 }
4881
4882 /*
4883  * Calls #HeadersFunc for each header already selected in the main
4884  * window or the message currently being shown in the msg view window
4885  */
4886 static void
4887 do_headers_action (ModestWindow *win, 
4888                    HeadersFunc func,
4889                    gpointer user_data)
4890 {
4891         TnyList *headers_list = NULL;
4892         TnyIterator *iter = NULL;
4893         TnyHeader *header = NULL;
4894         TnyFolder *folder = NULL;
4895
4896         /* Get headers */
4897         headers_list = get_selected_headers (win);
4898         if (!headers_list)
4899                 return;
4900
4901         /* Get the folder */
4902         iter = tny_list_create_iterator (headers_list);
4903         header = TNY_HEADER (tny_iterator_get_current (iter));
4904         if (header) {
4905                 folder = tny_header_get_folder (header);
4906                 g_object_unref (header);
4907         }
4908
4909         /* Call the function for each header */
4910         while (!tny_iterator_is_done (iter)) {
4911                 header = TNY_HEADER (tny_iterator_get_current (iter));
4912                 func (header, win, user_data);
4913                 g_object_unref (header);
4914                 tny_iterator_next (iter);
4915         }
4916
4917         /* Trick: do a poke status in order to speed up the signaling
4918            of observers */
4919         tny_folder_poke_status (folder);
4920
4921         /* Frees */
4922         g_object_unref (folder);
4923         g_object_unref (iter);
4924         g_object_unref (headers_list);
4925 }
4926
4927 void 
4928 modest_ui_actions_view_attachment (GtkAction *action,
4929                                    ModestWindow *window)
4930 {
4931         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4932                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4933         } else {
4934                 /* not supported window for this action */
4935                 g_return_if_reached ();
4936         }
4937 }
4938
4939 void
4940 modest_ui_actions_save_attachments (GtkAction *action,
4941                                     ModestWindow *window)
4942 {
4943         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4944                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4945         } else {
4946                 /* not supported window for this action */
4947                 g_return_if_reached ();
4948         }
4949 }
4950
4951 void
4952 modest_ui_actions_remove_attachments (GtkAction *action,
4953                                       ModestWindow *window)
4954 {
4955         if (MODEST_IS_MAIN_WINDOW (window)) {
4956                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4957         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4958                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4959         } else {
4960                 /* not supported window for this action */
4961                 g_return_if_reached ();
4962         }
4963 }
4964
4965 void 
4966 modest_ui_actions_on_settings (GtkAction *action, 
4967                                ModestWindow *win)
4968 {
4969         GtkWidget *dialog;
4970
4971         dialog = modest_platform_get_global_settings_dialog ();
4972         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4973         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4974         gtk_widget_show_all (dialog);
4975
4976         gtk_dialog_run (GTK_DIALOG (dialog));
4977
4978         gtk_widget_destroy (dialog);
4979 }
4980
4981 void 
4982 modest_ui_actions_on_help (GtkAction *action, 
4983                            GtkWindow *win)
4984 {
4985         const gchar *help_id;
4986
4987         g_return_if_fail (action);
4988         g_return_if_fail (win && GTK_IS_WINDOW(win));
4989         
4990         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
4991         
4992         if (help_id)
4993                 modest_platform_show_help (GTK_WINDOW (win), help_id);
4994         else
4995                 g_warning ("%s: no help for window %p", __FUNCTION__, win);
4996 }
4997
4998 static void
4999 retrieve_msg_contents_performer (gboolean canceled, 
5000                                  GError *err,
5001                                  GtkWindow *parent_window, 
5002                                  TnyAccount *account, 
5003                                  gpointer user_data)
5004 {
5005         ModestMailOperation *mail_op;
5006         TnyList *headers = TNY_LIST (user_data);
5007
5008         if (err || canceled) {
5009                 goto out;
5010         }
5011
5012         /* Create mail operation */
5013         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5014                                                                  modest_ui_actions_get_msgs_full_error_handler, 
5015                                                                  NULL, NULL);
5016         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5017         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
5018
5019         /* Frees */
5020         g_object_unref (mail_op);
5021  out:
5022         g_object_unref (headers);
5023         g_object_unref (account);
5024 }
5025
5026 void 
5027 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5028                                             ModestWindow *window)
5029 {
5030         TnyList *headers = NULL;
5031         TnyAccount *account = NULL;
5032         TnyIterator *iter = NULL;
5033         TnyHeader *header = NULL;
5034         TnyFolder *folder = NULL;
5035
5036         /* Get headers */
5037         headers = get_selected_headers (window);
5038         if (!headers)
5039                 return;
5040
5041         /* Pick the account */
5042         iter = tny_list_create_iterator (headers);
5043         header = TNY_HEADER (tny_iterator_get_current (iter));
5044         folder = tny_header_get_folder (header);
5045         account = tny_folder_get_account (folder);
5046         g_object_unref (folder);
5047         g_object_unref (header);
5048         g_object_unref (iter);
5049
5050         /* Connect and perform the message retrieval */
5051         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5052                                              g_object_ref (account), 
5053                                              retrieve_msg_contents_performer, 
5054                                              g_object_ref (headers));
5055
5056         /* Frees */
5057         g_object_unref (account);
5058         g_object_unref (headers);
5059 }
5060
5061 void
5062 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5063 {
5064         g_return_if_fail (MODEST_IS_WINDOW (window));
5065
5066         /* Update dimmed */
5067         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5068 }
5069
5070 void
5071 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5072 {
5073         g_return_if_fail (MODEST_IS_WINDOW (window));
5074
5075         /* Update dimmed */
5076         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5077 }
5078
5079 void
5080 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5081                                           ModestWindow *window)
5082 {
5083         g_return_if_fail (MODEST_IS_WINDOW (window));
5084         
5085         /* Update dimmed */
5086         modest_ui_actions_check_menu_dimming_rules (window);
5087 }
5088
5089 void
5090 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5091                                           ModestWindow *window)
5092 {
5093         g_return_if_fail (MODEST_IS_WINDOW (window));
5094
5095         /* Update dimmed */
5096         modest_ui_actions_check_menu_dimming_rules (window);
5097 }
5098
5099 void
5100 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5101                                           ModestWindow *window)
5102 {
5103         g_return_if_fail (MODEST_IS_WINDOW (window));
5104
5105         /* Update dimmed */
5106         modest_ui_actions_check_menu_dimming_rules (window);
5107 }
5108
5109 void
5110 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5111                                             ModestWindow *window)
5112 {
5113         g_return_if_fail (MODEST_IS_WINDOW (window));
5114
5115         /* Update dimmed */
5116         modest_ui_actions_check_menu_dimming_rules (window);
5117 }
5118
5119 void
5120 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5121                                           ModestWindow *window)
5122 {
5123         g_return_if_fail (MODEST_IS_WINDOW (window));
5124
5125         /* Update dimmed */
5126         modest_ui_actions_check_menu_dimming_rules (window);
5127 }
5128
5129 void
5130 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5131                                           ModestWindow *window)
5132 {
5133         g_return_if_fail (MODEST_IS_WINDOW (window));
5134
5135         /* Update dimmed */
5136         modest_ui_actions_check_menu_dimming_rules (window);
5137 }
5138
5139 void
5140 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5141                                                  ModestWindow *window)
5142 {
5143         g_return_if_fail (MODEST_IS_WINDOW (window));
5144
5145         /* Update dimmed */
5146         modest_ui_actions_check_menu_dimming_rules (window);
5147 }
5148
5149 void
5150 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5151                                                      ModestWindow *window)
5152 {
5153         g_return_if_fail (MODEST_IS_WINDOW (window));
5154
5155         /* Update dimmed */
5156         modest_ui_actions_check_menu_dimming_rules (window);
5157 }
5158
5159 void
5160 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5161                                                      ModestWindow *window)
5162 {
5163         g_return_if_fail (MODEST_IS_WINDOW (window));
5164
5165         /* Update dimmed */
5166         modest_ui_actions_check_menu_dimming_rules (window);
5167 }
5168
5169 void
5170 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5171 {
5172         g_return_if_fail (MODEST_IS_WINDOW (window));
5173
5174         modest_platform_show_search_messages (GTK_WINDOW (window));
5175 }
5176
5177 void     
5178 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5179 {
5180         g_return_if_fail (MODEST_IS_WINDOW (win));
5181         modest_platform_show_addressbook (GTK_WINDOW (win));
5182 }
5183
5184
5185 void
5186 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5187                                           ModestWindow *window)
5188 {
5189         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5190
5191         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5192 }
5193
5194 static void 
5195 on_send_receive_finished (ModestMailOperation  *mail_op, 
5196                            gpointer user_data)
5197 {
5198         GtkWidget *header_view, *folder_view;
5199         TnyFolderStore *folder_store;
5200         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5201
5202         /* Set send/receive operation finished */       
5203         modest_main_window_notify_send_receive_completed (main_win);
5204
5205         /* Don't refresh the current folder if there were any errors */
5206         if (modest_mail_operation_get_status (mail_op) !=
5207             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5208                 return;
5209         
5210         /* Refresh the current folder if we're viewing a window. We do
5211            this because the user won't be able to see the new mails in
5212            the selected folder after a Send&Receive because it only
5213            performs a poke_status, i.e, only the number of read/unread
5214            messages is updated, but the new headers are not
5215            downloaded */
5216         folder_view = modest_main_window_get_child_widget (main_win, 
5217                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5218         if (!folder_view)
5219                 return;
5220
5221         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5222         
5223         /* Do not need to refresh INBOX again because the
5224            update_account does it always automatically */
5225         if (folder_store && TNY_IS_FOLDER (folder_store) && 
5226             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5227                 ModestMailOperation *refresh_op;
5228
5229                 header_view = modest_main_window_get_child_widget (main_win,
5230                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5231                 
5232                 /* We do not need to set the contents style
5233                    because it hasn't changed. We also do not
5234                    need to save the widget status. Just force
5235                    a refresh */
5236                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5237                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5238                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5239                                                       folder_refreshed_cb, main_win);
5240                 g_object_unref (refresh_op);
5241         }
5242         
5243         if (folder_store)
5244                 g_object_unref (folder_store);
5245 }
5246
5247
5248 void 
5249 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
5250                                                 TnyHeader *header, 
5251                                                 TnyMsg *msg, 
5252                                                 GError *err, 
5253                                                 gpointer user_data)
5254 {
5255         const gchar* server_name = NULL;
5256         TnyTransportAccount *server_account;
5257         gchar *message = NULL;
5258
5259         /* Don't show anything if the user cancelled something */
5260         if (err->code == TNY_TRANSPORT_ACCOUNT_ERROR_SEND_USER_CANCEL)
5261                 return;
5262
5263         /* Get the server name: */
5264         server_account = 
5265                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
5266         if (server_account) {
5267                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
5268                         
5269                 g_object_unref (server_account);
5270                 server_account = NULL;
5271         }
5272         
5273         g_return_if_fail (server_name);
5274
5275         /* Show the appropriate message text for the GError: */
5276         switch (err->code) {
5277         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
5278                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5279                 break;
5280         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
5281                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5282                 break;
5283         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
5284                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
5285                 break;
5286         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
5287                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
5288                 break;
5289         default:
5290                 g_warning ("%s: unexpected TNY_TRANSPORT_ACCOUNT_ERROR %d",
5291                            __FUNCTION__, err->code);
5292                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
5293                 break;  
5294         }
5295         
5296         /* TODO if the username or the password where not defined we
5297            should show the Accounts Settings dialog or the Connection
5298            specific SMTP server window */
5299
5300         modest_platform_run_information_dialog (NULL, message);
5301         g_free (message);
5302 }
5303
5304 void
5305 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5306                                                 gchar *msg_id, 
5307                                                 guint status,
5308                                                 gpointer user_data)
5309 {
5310         ModestMainWindow *main_window = NULL;
5311         ModestWindowMgr *mgr = NULL;
5312         GtkWidget *folder_view = NULL, *header_view = NULL;
5313         TnyFolderStore *selected_folder = NULL;
5314         TnyFolderType folder_type;
5315
5316         mgr = modest_runtime_get_window_mgr ();
5317         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
5318                                                                              FALSE));/* don't create */
5319         if (!main_window)
5320                 return;
5321
5322         /* Check if selected folder is OUTBOX */
5323         folder_view = modest_main_window_get_child_widget (main_window,
5324                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5325         header_view = modest_main_window_get_child_widget (main_window,
5326                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5327
5328         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5329         if (!TNY_IS_FOLDER (selected_folder)) 
5330                 goto frees;
5331
5332         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5333 #if GTK_CHECK_VERSION(2, 8, 0) 
5334         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
5335         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
5336                 GtkTreeViewColumn *tree_column;
5337
5338                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
5339                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5340                 gtk_tree_view_column_queue_resize (tree_column);
5341         }
5342 #else
5343         gtk_widget_queue_draw (header_view);
5344 #endif          
5345         
5346         /* Free */
5347  frees:
5348         if (selected_folder != NULL)
5349                 g_object_unref (selected_folder);
5350 }
5351
5352 void 
5353 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
5354                                                TnyAccount *account)
5355 {
5356         ModestTransportStoreProtocol proto;
5357         const gchar *proto_name;
5358         gchar *error_note = NULL;
5359         
5360         proto_name = tny_account_get_proto (account);
5361         proto = modest_protocol_info_get_transport_store_protocol (proto_name);
5362         
5363         switch (proto) {
5364         case MODEST_PROTOCOL_STORE_POP:
5365                 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"), 
5366                                               tny_account_get_hostname (account));
5367                 break;
5368         case MODEST_PROTOCOL_STORE_IMAP:
5369                 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"), 
5370                                               tny_account_get_hostname (account));
5371                 break;
5372         case MODEST_PROTOCOL_STORE_MAILDIR:
5373         case MODEST_PROTOCOL_STORE_MBOX:
5374                 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
5375                 break;
5376         default:
5377                 g_warning ("%s: This should not be reached", __FUNCTION__);
5378         }
5379
5380         if (error_note) {
5381                 modest_platform_run_information_dialog (parent_window, error_note);
5382                 g_free (error_note);
5383         }
5384 }