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