Do ignore '\n' when splitting addresses
[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-defs.h>
39 #include <modest-tny-folder.h>
40 #include <modest-tny-msg.h>
41 #include <modest-tny-account.h>
42 #include <modest-address-book.h>
43 #include "modest-error.h"
44 #include "modest-ui-actions.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-error.h>
50 #include <tny-camel-folder.h>
51 #include <tny-camel-imap-folder.h>
52 #include <tny-camel-pop-folder.h>
53 #ifdef MODEST_TOOLKIT_HILDON2
54 #include <modest-accounts-window.h>
55 #include <hildon/hildon-gtk.h>
56 #include <modest-header-window.h>
57 #include <modest-folder-window.h>
58 #include <modest-maemo-utils.h>
59 #endif
60 #include "modest-utils.h"
61 #include "widgets/modest-connection-specific-smtp-window.h"
62 #include "widgets/modest-ui-constants.h"
63 #include <widgets/modest-main-window.h>
64 #include <widgets/modest-msg-view-window.h>
65 #include <widgets/modest-account-view-window.h>
66 #include <widgets/modest-details-dialog.h>
67 #include <widgets/modest-attachments-view.h>
68 #include "widgets/modest-folder-view.h"
69 #include "widgets/modest-global-settings-dialog.h"
70 #include "modest-account-mgr-helpers.h"
71 #include "modest-mail-operation.h"
72 #include "modest-text-utils.h"
73 #include <modest-widget-memory.h>
74 #include <tny-error.h>
75 #include <tny-simple-list.h>
76 #include <tny-msg-view.h>
77 #include <tny-device.h>
78 #include <tny-merge-folder.h>
79
80 #include <gtkhtml/gtkhtml.h>
81
82 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
83
84 typedef struct _GetMsgAsyncHelper {
85         ModestWindow *window;
86         ModestMailOperation *mail_op;
87         TnyIterator *iter;
88         guint num_ops;
89         GFunc func;
90         gpointer user_data;
91 } GetMsgAsyncHelper;
92
93 typedef enum _ReplyForwardAction {
94         ACTION_REPLY,
95         ACTION_REPLY_TO_ALL,
96         ACTION_FORWARD
97 } ReplyForwardAction;
98
99 typedef struct _ReplyForwardHelper {
100         guint reply_forward_type;
101         ReplyForwardAction action;
102         gchar *account_name;
103         gchar *mailbox;
104         GtkWidget *parent_window;
105         TnyHeader *header;
106 } ReplyForwardHelper;
107
108 typedef struct _MoveToHelper {
109         GtkTreeRowReference *reference;
110         GtkWidget *banner;
111 } MoveToHelper;
112
113 typedef struct _PasteAsAttachmentHelper {
114         ModestMsgEditWindow *window;
115         GtkWidget *banner;
116 } PasteAsAttachmentHelper;
117
118 typedef struct {
119         TnyList *list;
120         ModestWindow *win;
121 } MoveToInfo;
122
123 /*
124  * The do_headers_action uses this kind of functions to perform some
125  * action to each member of a list of headers
126  */
127 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
128
129 static void     do_headers_action     (ModestWindow *win,
130                                        HeadersFunc func,
131                                        gpointer user_data);
132
133 static void     open_msg_cb            (ModestMailOperation *mail_op,
134                                         TnyHeader *header,
135                                         gboolean canceled,
136                                         TnyMsg *msg,
137                                         GError *err,
138                                         gpointer user_data);
139
140 static void     reply_forward_cb       (ModestMailOperation *mail_op,
141                                         TnyHeader *header,
142                                         gboolean canceled,
143                                         TnyMsg *msg,
144                                         GError *err,
145                                         gpointer user_data);
146
147 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
148
149 #ifndef MODEST_TOOLKIT_HILDON2
150 static void     folder_refreshed_cb    (ModestMailOperation *mail_op,
151                                         TnyFolder *folder,
152                                         gpointer user_data);
153
154 static void     on_send_receive_finished (ModestMailOperation  *mail_op,
155                                           gpointer user_data);
156 #endif
157
158 static gint header_list_count_uncached_msgs (TnyList *header_list);
159
160 static gboolean connect_to_get_msg (ModestWindow *win,
161                                     gint num_of_uncached_msgs,
162                                     TnyAccount *account);
163
164 static gboolean remote_folder_has_leave_on_server (TnyFolderStore *folder);
165
166 static void     do_create_folder (GtkWindow *window,
167                                   TnyFolderStore *parent_folder,
168                                   const gchar *suggested_name);
169
170 static TnyAccount *get_account_from_folder_store (TnyFolderStore *folder_store);
171
172 #ifndef MODEST_TOOLKIT_HILDON2
173 static void modest_ui_actions_on_main_window_move_to (GtkAction *action,
174                                                       GtkWidget *folder_view,
175                                                       TnyFolderStore *dst_folder,
176                                                       ModestMainWindow *win);
177
178 #else
179 static void modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
180                                                         TnyFolderStore *dst_folder,
181                                                         TnyList *selection,
182                                                         GtkWindow *win);
183 #endif
184
185 static void modest_ui_actions_on_window_move_to (GtkAction *action,
186                                                  TnyList *list_to_move,
187                                                  TnyFolderStore *dst_folder,
188                                                  ModestWindow *win);
189
190 /*
191  * This function checks whether a TnyFolderStore is a pop account
192  */
193 static gboolean
194 remote_folder_has_leave_on_server (TnyFolderStore *folder)
195 {
196         TnyAccount *account;
197         gboolean result;
198
199         g_return_val_if_fail (TNY_IS_FOLDER_STORE (folder), FALSE);
200
201         account = get_account_from_folder_store (folder);
202         result = (modest_protocol_registry_protocol_type_has_leave_on_server (modest_runtime_get_protocol_registry (),
203                                                                               modest_tny_account_get_protocol_type (account)));
204         g_object_unref (account);
205
206         return result;
207 }
208
209 /* FIXME: this should be merged with the similar code in modest-account-view-window */
210 /* Show the account creation wizard dialog.
211  * returns: TRUE if an account was created. FALSE if the user cancelled.
212  */
213 gboolean
214 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
215 {
216         gboolean result = FALSE;
217         GtkWindow *wizard;
218         gint dialog_response;
219
220         /* there is no such wizard yet */
221         wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
222         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (wizard), (GtkWindow *) win);
223
224 #ifndef MODEST_TOOLKIT_HILDON2
225         /* always present a main window in the background
226          * we do it here, so we cannot end up with two wizards (as this
227          * function might be called in modest_window_mgr_get_main_window as well */
228         if (!win)
229                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
230                                                          TRUE);  /* create if not existent */
231 #else
232         if (!win) {
233                 GList *window_list;
234                 ModestWindowMgr *mgr;
235
236                 mgr = modest_runtime_get_window_mgr ();
237
238                 window_list = modest_window_mgr_get_window_list (mgr);
239                 if (window_list == NULL) {
240                         win = MODEST_WINDOW (modest_accounts_window_new ());
241                         if (modest_window_mgr_register_window (mgr, win, NULL)) {
242                                 gtk_widget_show_all (GTK_WIDGET (win));
243                         } else {
244                                 gtk_widget_destroy (GTK_WIDGET (win));
245                                 win = NULL;
246                         }
247
248                 } else {
249                         g_list_free (window_list);
250                 }
251         }
252 #endif
253
254         if (win)
255                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
256
257         /* make sure the mainwindow is visible. We need to present the
258            wizard again to give it the focus back. show_all are needed
259            in order to get the widgets properly drawn (MainWindow main
260            paned won't be in its right position and the dialog will be
261            missplaced */
262 #ifndef MODEST_TOOLKIT_HILDON2
263         gtk_widget_show_all (GTK_WIDGET (win));
264         gtk_widget_show_all (GTK_WIDGET (wizard));
265         gtk_window_present (GTK_WINDOW (win));
266         gtk_window_present (GTK_WINDOW (wizard));
267 #endif
268
269         dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
270         gtk_widget_destroy (GTK_WIDGET (wizard));
271         if (gtk_events_pending ())
272                 gtk_main_iteration ();
273
274         if (dialog_response == GTK_RESPONSE_CANCEL) {
275                 result = FALSE;
276         } else {
277                 /* Check whether an account was created: */
278                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
279         }
280         return result;
281 }
282
283
284 void
285 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
286 {
287         GtkWidget *about;
288         const gchar *authors[] = {
289                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
290                 NULL
291         };
292         about = gtk_about_dialog_new ();
293         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
294         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
295         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
296                                         _("Copyright (c) 2006, Nokia Corporation\n"
297                                           "All rights reserved."));
298         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
299                                        _("a modest e-mail client\n\n"
300                                          "design and implementation: Dirk-Jan C. Binnema\n"
301                                          "contributions from the fine people at KC and Ig\n"
302                                          "uses the tinymail email framework written by Philip van Hoof"));
303         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
304         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
305         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
306         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
307
308         gtk_dialog_run (GTK_DIALOG (about));
309         gtk_widget_destroy(about);
310 }
311
312 /*
313  * Gets the list of currently selected messages. If the win is the
314  * main window, then it returns a newly allocated list of the headers
315  * selected in the header view. If win is the msg view window, then
316  * the value returned is a list with just a single header.
317  *
318  * The caller of this funcion must free the list.
319  */
320 static TnyList *
321 get_selected_headers (ModestWindow *win)
322 {
323         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
324                 /* for MsgViewWindows, we simply return a list with one element */
325                 TnyHeader *header;
326                 TnyList *list = NULL;
327
328                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
329                 if (header != NULL) {
330                         list = tny_simple_list_new ();
331                         tny_list_prepend (list, G_OBJECT(header));
332                         g_object_unref (G_OBJECT(header));
333                 }
334
335                 return list;
336 #ifndef MODEST_TOOLKIT_HILDON2
337         } else if (MODEST_IS_MAIN_WINDOW(win)) {
338                 GtkWidget *header_view;
339
340                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
341                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
342                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
343 #else
344         } else if (MODEST_IS_HEADER_WINDOW (win)) {
345                 GtkWidget *header_view;
346
347                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
348                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
349 #endif
350         } else {
351                 return NULL;
352         }
353 }
354
355 #ifndef MODEST_TOOLKIT_HILDON2
356 static GtkTreeRowReference *
357 get_next_after_selected_headers (ModestHeaderView *header_view)
358 {
359         GtkTreeSelection *sel;
360         GList *selected_rows, *node;
361         GtkTreePath *path;
362         GtkTreeRowReference *result;
363         GtkTreeModel *model;
364
365         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
366         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
367         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
368
369         if (selected_rows == NULL)
370                 return NULL;
371
372         node = g_list_last (selected_rows);
373         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
374         gtk_tree_path_next (path);
375
376         result = gtk_tree_row_reference_new (model, path);
377
378         gtk_tree_path_free (path);
379         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
380         g_list_free (selected_rows);
381
382         return result;
383 }
384 #endif
385
386 static void
387 headers_action_mark_as_read (TnyHeader *header,
388                              ModestWindow *win,
389                              gpointer user_data)
390 {
391         TnyHeaderFlags flags;
392
393         g_return_if_fail (TNY_IS_HEADER(header));
394
395         flags = tny_header_get_flags (header);
396         if (flags & TNY_HEADER_FLAG_SEEN) return;
397         tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
398 }
399
400 static void
401 headers_action_mark_as_unread (TnyHeader *header,
402                                ModestWindow *win,
403                                gpointer user_data)
404 {
405         TnyHeaderFlags flags;
406
407         g_return_if_fail (TNY_IS_HEADER(header));
408
409         flags = tny_header_get_flags (header);
410         if (flags & TNY_HEADER_FLAG_SEEN)  {
411                 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
412         }
413 }
414
415 /** After deleing a message that is currently visible in a window,
416  * show the next message from the list, or close the window if there are no more messages.
417  **/
418 void
419 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
420 {
421         /* Close msg view window or select next */
422         if (!modest_msg_view_window_select_next_message (win) &&
423             !modest_msg_view_window_select_previous_message (win)) {
424                 gboolean ret_value;
425                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
426         }
427 }
428
429
430 void
431 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
432 {
433         modest_ui_actions_on_edit_mode_delete_message (win);
434 }
435
436 gboolean
437 modest_ui_actions_on_edit_mode_delete_message (ModestWindow *win)
438 {
439         TnyList *header_list = NULL;
440         TnyIterator *iter = NULL;
441         TnyHeader *header = NULL;
442         gchar *message = NULL;
443         gchar *desc = NULL;
444         gint response;
445         ModestWindowMgr *mgr;
446         gboolean retval = TRUE;
447
448         g_return_val_if_fail (MODEST_IS_WINDOW(win), FALSE);
449
450 #ifndef MODEST_TOOLKIT_HILDON2
451         /* Check first if the header view has the focus */
452         if (MODEST_IS_MAIN_WINDOW (win)) {
453                 GtkWidget *header_view = NULL;
454
455                 header_view =
456                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
457                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
458                 if (!gtk_widget_is_focus (header_view))
459                         return FALSE;
460         }
461 #endif
462         /* Get the headers, either from the header view (if win is the main window),
463          * or from the message view window: */
464         header_list = get_selected_headers (win);
465         if (!header_list) return FALSE;
466
467         /* Check if any of the headers are already opened, or in the process of being opened */
468 #ifndef MODEST_TOOLKIT_HILDON2
469         if (MODEST_IS_MAIN_WINDOW (win)) {
470                 gint opened_headers = 0;
471
472                 iter = tny_list_create_iterator (header_list);
473                 mgr = modest_runtime_get_window_mgr ();
474                 while (!tny_iterator_is_done (iter)) {
475                         header = TNY_HEADER (tny_iterator_get_current (iter));
476                         if (header) {
477                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
478                                         opened_headers++;
479                                 g_object_unref (header);
480                         }
481                         tny_iterator_next (iter);
482                 }
483                 g_object_unref (iter);
484
485                 if (opened_headers > 0) {
486                         gchar *msg;
487
488                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"),
489                                                opened_headers);
490
491                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg, FALSE);
492
493                         g_free (msg);
494                         g_object_unref (header_list);
495                         return FALSE;
496                 }
497         }
498 #endif
499
500         /* Select message */
501         if (tny_list_get_length(header_list) == 1) {
502                 iter = tny_list_create_iterator (header_list);
503                 header = TNY_HEADER (tny_iterator_get_current (iter));
504                 if (header) {
505                         gchar *subject;
506                         subject = tny_header_dup_subject (header);
507                         if (!subject)
508                                 subject = g_strdup (_("mail_va_no_subject"));
509                         desc = g_strdup_printf ("%s", subject);
510                         g_free (subject);
511                         g_object_unref (header);
512                 }
513
514                 g_object_unref (iter);
515         }
516         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages",
517                                            tny_list_get_length(header_list)), desc);
518
519         /* Confirmation dialog */
520         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
521                                                             message);
522
523         if (response == GTK_RESPONSE_OK) {
524                 GtkTreeSelection *sel = NULL;
525                 GList *sel_list = NULL;
526                 ModestMailOperation *mail_op = NULL;
527
528                 /* Find last selected row */
529 #ifndef MODEST_TOOLKIT_HILDON2
530                 if (MODEST_IS_MAIN_WINDOW (win)) {
531                         GList *tmp = NULL;
532                         ModestWindowMgr *mgr = NULL;
533                         GtkTreeModel *model = NULL;
534                         GtkTreeRowReference *next_row_reference = NULL, *prev_row_reference = NULL;
535                         GtkTreePath *next_path = NULL, *prev_path = NULL;
536
537                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
538                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
539                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
540                         for (tmp=sel_list; tmp; tmp=tmp->next) {
541                                 if (tmp->next == NULL) {
542                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
543                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
544
545                                         gtk_tree_path_prev (prev_path);
546                                         gtk_tree_path_next (next_path);
547
548                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
549                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
550                                 }
551                         }
552                 }
553 #endif
554
555                 /* Disable window dimming management */
556                 modest_window_disable_dimming (win);
557
558                 /* Remove each header. If it's a view window header_view == NULL */
559                 mail_op = modest_mail_operation_new ((GObject *) win);
560                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
561                                                  mail_op);
562                 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
563                 g_object_unref (mail_op);
564
565                 /* Enable window dimming management */
566                 if (sel != NULL) {
567                         gtk_tree_selection_unselect_all (sel);
568                 }
569                 modest_window_enable_dimming (win);
570
571                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
572                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
573
574                         /* Get main window */
575                         mgr = modest_runtime_get_window_mgr ();
576 #ifndef MODEST_TOOLKIT_HILDON2
577                 } else if (MODEST_IS_MAIN_WINDOW (win)) {
578                         /* Select next or previous row */
579                         if (gtk_tree_row_reference_valid (next_row_reference)) {
580                                 gtk_tree_selection_select_path (sel, next_path);
581                         }
582                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {
583                                 gtk_tree_selection_select_path (sel, prev_path);
584                         }
585
586                         /* Free */
587                         if (gtk_tree_row_reference_valid (next_row_reference))
588                                 gtk_tree_row_reference_free (next_row_reference);
589                         if (next_path != NULL)
590                                 gtk_tree_path_free (next_path);
591                         if (gtk_tree_row_reference_valid (prev_row_reference))
592                                 gtk_tree_row_reference_free (prev_row_reference);
593                         if (prev_path != NULL)
594                                 gtk_tree_path_free (prev_path);
595 #endif
596                 }
597
598                 /* Update toolbar dimming state */
599                 modest_ui_actions_check_menu_dimming_rules (win);
600                 modest_ui_actions_check_toolbar_dimming_rules (win);
601
602                 /* Free */
603                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
604                 g_list_free (sel_list);
605                 retval = TRUE;
606         } else {
607                 retval = FALSE;
608         }
609
610         /* Free*/
611         g_free(message);
612         g_free(desc);
613         g_object_unref (header_list);
614
615         return retval;
616 }
617
618
619
620
621 /* delete either message or folder, based on where we are */
622 void
623 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
624 {
625         g_return_if_fail (MODEST_IS_WINDOW(win));
626
627         /* Check first if the header view has the focus */
628 #ifndef MODEST_TOOLKIT_HILDON2
629         if (MODEST_IS_MAIN_WINDOW (win)) {
630                 GtkWidget *w;
631                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
632                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
633                 if (gtk_widget_is_focus (w)) {
634                         modest_ui_actions_on_delete_folder (action, MODEST_WINDOW(win));
635                         return;
636                 }
637         }
638 #endif
639         modest_ui_actions_on_delete_message (action, win);
640 }
641
642 void
643 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
644 {
645         ModestWindowMgr *mgr = NULL;
646
647 #ifdef MODEST_PLATFORM_MAEMO
648         modest_window_mgr_save_state_for_all_windows (modest_runtime_get_window_mgr ());
649 #endif /* MODEST_PLATFORM_MAEMO */
650
651         g_debug ("closing down, clearing %d item(s) from operation queue",
652                  modest_mail_operation_queue_num_elements
653                  (modest_runtime_get_mail_operation_queue()));
654
655         /* cancel all outstanding operations */
656         modest_mail_operation_queue_cancel_all
657                 (modest_runtime_get_mail_operation_queue());
658
659         g_debug ("queue has been cleared");
660
661
662         /* Check if there are opened editing windows */
663         mgr = modest_runtime_get_window_mgr ();
664         modest_window_mgr_close_all_windows (mgr);
665
666         /* note: when modest-tny-account-store is finalized,
667            it will automatically set all network connections
668            to offline */
669
670 /*      gtk_main_quit (); */
671 }
672
673 void
674 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
675 {
676         gboolean ret_value;
677
678         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
679
680 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
681 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
682 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
683 /*              gboolean ret_value; */
684 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
685 /*      } else if (MODEST_IS_WINDOW (win)) { */
686 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
687 /*      } else { */
688 /*              g_return_if_reached (); */
689 /*      } */
690 }
691
692 void
693 modest_ui_actions_add_to_contacts (GtkAction *action, ModestWindow *win)
694 {
695         if (MODEST_IS_MSG_VIEW_WINDOW (win))
696                 modest_msg_view_window_add_to_contacts (MODEST_MSG_VIEW_WINDOW (win));
697         else if (MODEST_IS_MSG_EDIT_WINDOW (win))
698                 modest_msg_edit_window_add_to_contacts (MODEST_MSG_EDIT_WINDOW (win));
699 }
700
701 void
702 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
703 {
704         GtkClipboard *clipboard = NULL;
705         gchar *selection = NULL;
706
707         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
708         selection = gtk_clipboard_wait_for_text (clipboard);
709
710         if (selection) {
711                 modest_address_book_add_address (selection, (GtkWindow *) win);
712                 g_free (selection);
713         }
714 }
715
716 void
717 modest_ui_actions_on_new_account (GtkAction *action,
718                                   ModestWindow *window)
719 {
720         if (!modest_ui_actions_run_account_setup_wizard (window)) {
721                 g_debug ("%s: wizard was already running", __FUNCTION__);
722         }
723 }
724
725 void
726 modest_ui_actions_on_accounts (GtkAction *action,
727                                ModestWindow *win)
728 {
729         /* This is currently only implemented for Maemo */
730         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
731                 if (!modest_ui_actions_run_account_setup_wizard (win))
732                         g_debug ("%s: wizard was already running", __FUNCTION__);
733
734                 return;
735         } else {
736                 /* Show the list of accounts */
737                 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
738
739                 /* The accounts dialog must be modal */
740                 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (account_win), (GtkWindow *) win);
741                 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win));
742         }
743 }
744
745 void
746 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
747 {
748         /* This is currently only implemented for Maemo,
749          * because it requires an API (libconic) to detect different connection
750          * possiblities.
751          */
752 #ifndef MODEST_TOOLKIT_GTK /* Defined in config.h */
753
754         /* Create the window if necessary: */
755         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
756         modest_connection_specific_smtp_window_fill_with_connections (
757                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
758                 modest_runtime_get_account_mgr());
759
760         /* Show the window: */
761         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
762                                      GTK_WINDOW (specific_window), (GtkWindow *) win);
763         gtk_widget_show (specific_window);
764 #endif /* !MODEST_TOOLKIT_GTK */
765 }
766
767 static guint64
768 count_part_size (const gchar *part)
769 {
770         GnomeVFSURI *vfs_uri;
771         gchar *escaped_filename;
772         gchar *filename;
773         GnomeVFSFileInfo *info;
774         guint64 result;
775
776         /* Estimation of attachment size if we cannot get it from file info */
777         result = 32768;
778
779         vfs_uri = gnome_vfs_uri_new (part);
780
781         escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
782         filename = gnome_vfs_unescape_string_for_display (escaped_filename);
783         g_free (escaped_filename);
784         gnome_vfs_uri_unref (vfs_uri);
785
786         info = gnome_vfs_file_info_new ();
787         
788         if (gnome_vfs_get_file_info (part, 
789                                      info, 
790                                      GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
791             == GNOME_VFS_OK) {
792                 if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
793                         result = info->size;
794                 }
795         }
796         g_free (filename);
797         gnome_vfs_file_info_unref (info);
798
799         return result;
800 }
801
802 static guint64 
803 count_parts_size (GSList *parts)
804 {
805         GSList *node;
806         guint64 result = 0;
807
808         for (node = parts; node != NULL; node = g_slist_next (node)) {
809                 result += count_part_size ((const gchar *) node->data);
810         }
811
812         return result;
813 }
814
815 void
816 modest_ui_actions_compose_msg(ModestWindow *win,
817                               const gchar *to_str,
818                               const gchar *cc_str,
819                               const gchar *bcc_str,
820                               const gchar *subject_str,
821                               const gchar *body_str,
822                               GSList *attachments,
823                               gboolean set_as_modified)
824 {
825         gchar *account_name = NULL;
826         const gchar *mailbox;
827         TnyMsg *msg = NULL;
828         TnyAccount *account = NULL;
829         TnyFolder *folder = NULL;
830         gchar *from_str = NULL, *signature = NULL, *body = NULL;
831         gchar *recipient = NULL;
832         gboolean use_signature = FALSE;
833         ModestWindow *msg_win = NULL;
834         ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
835         ModestTnyAccountStore *store = modest_runtime_get_account_store();
836         GnomeVFSFileSize total_size, allowed_size;
837         guint64 available_disk, expected_size, parts_size;
838         guint parts_count;
839
840         /* we check for low-mem */
841         if (modest_platform_check_memory_low (win, TRUE))
842                 goto cleanup;
843
844         available_disk = modest_utils_get_available_space (NULL);
845         parts_count = g_slist_length (attachments);
846         parts_size = count_parts_size (attachments);
847         expected_size = modest_tny_msg_estimate_size (body, NULL, parts_count, parts_size);
848
849         /* Double check: disk full condition or message too big */
850         if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
851             expected_size > available_disk) {
852                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
853                 modest_platform_system_banner (NULL, NULL, msg);
854                 g_free (msg);
855
856                 return;
857         }
858
859         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
860                 modest_platform_run_information_dialog (
861                         GTK_WINDOW(win),
862                         _("mail_ib_error_attachment_size"),
863                         TRUE);
864                 return;
865         }
866
867
868 #ifdef MODEST_TOOLKIT_HILDON2
869         if (win)
870                 account_name = g_strdup (modest_window_get_active_account(win));
871 #endif
872         if (!account_name) {
873                 account_name = modest_account_mgr_get_default_account(mgr);
874         }
875         if (!account_name) {
876                 g_printerr ("modest: no account found\n");
877                 goto cleanup;
878         }
879
880         if (win)
881                 mailbox = modest_window_get_active_mailbox (win);
882         else
883                 mailbox = NULL;
884         account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
885         if (!account) {
886                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
887                 goto cleanup;
888         }
889         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
890         if (!folder) {
891                 g_printerr ("modest: failed to find Drafts folder\n");
892                 goto cleanup;
893         }
894         from_str = modest_account_mgr_get_from_string (mgr, account_name, mailbox);
895         if (!from_str) {
896                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
897                 goto cleanup;
898         }
899
900         recipient = modest_text_utils_get_email_address (from_str);
901         signature = modest_account_mgr_get_signature_from_recipient (mgr, recipient, &use_signature);
902         g_free (recipient);
903         if (body_str != NULL) {
904                 body = use_signature ? g_strconcat(body_str, "\n",
905                                                    MODEST_TEXT_UTILS_SIGNATURE_MARKER,
906                                                    "\n", signature, NULL) : g_strdup(body_str);
907         } else {
908                 body = use_signature ? g_strconcat("\n", MODEST_TEXT_UTILS_SIGNATURE_MARKER,
909                                                    "\n", signature, NULL) : g_strdup("");
910         }
911
912         msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, NULL, NULL, body, NULL, NULL, NULL);
913         if (!msg) {
914                 g_printerr ("modest: failed to create new msg\n");
915                 goto cleanup;
916         }
917
918         /* Create and register edit window */
919         /* This is destroyed by TODO. */
920         total_size = 0;
921         allowed_size = MODEST_MAX_ATTACHMENT_SIZE;
922         msg_win = modest_msg_edit_window_new (msg, account_name, mailbox, FALSE);
923
924         if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win, win)) {
925                 gtk_widget_destroy (GTK_WIDGET (msg_win));
926                 goto cleanup;
927         }
928         modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
929         gtk_widget_show_all (GTK_WIDGET (msg_win));
930
931         while (attachments) {
932                 GnomeVFSFileSize att_size;
933                 att_size =
934                         modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
935                                                                attachments->data, allowed_size);
936                 total_size += att_size;
937
938                 if (att_size > allowed_size) {
939                         g_debug ("%s: total size: %u",
940                                  __FUNCTION__, (unsigned int)total_size);
941                         break;
942                 }
943                 allowed_size -= att_size;
944
945                 attachments = g_slist_next(attachments);
946         }
947
948 cleanup:
949         g_free (from_str);
950         g_free (signature);
951         g_free (body);
952         g_free (account_name);
953         if (account)
954                 g_object_unref (G_OBJECT(account));
955         if (folder)
956                 g_object_unref (G_OBJECT(folder));
957         if (msg)
958                 g_object_unref (G_OBJECT(msg));
959 }
960
961 void
962 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
963 {
964         /* if there are no accounts yet, just show the wizard */
965         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
966                 if (!modest_ui_actions_run_account_setup_wizard (win))
967                         return;
968
969         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
970 }
971
972
973 gboolean
974 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
975                                        TnyHeader *header,
976                                        TnyMsg *msg)
977 {
978         ModestMailOperationStatus status;
979
980         /* If there is no message or the operation was not successful */
981         status = modest_mail_operation_get_status (mail_op);
982         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
983                 const GError *error;
984
985                 /* If it's a memory low issue, then show a banner */
986                 error = modest_mail_operation_get_error (mail_op);
987                 if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
988                     error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
989                         GObject *source = modest_mail_operation_get_source (mail_op);
990                         modest_platform_run_information_dialog (GTK_IS_WINDOW (source) ? GTK_WINDOW (source) : NULL,
991                                                                 _KR("memr_ib_operation_disabled"),
992                                                                 TRUE);
993                         g_object_unref (source);
994                 }
995
996                 if (error && ((error->code == TNY_SERVICE_ERROR_NO_SUCH_MESSAGE) ||
997                               error->code == TNY_SERVICE_ERROR_MESSAGE_NOT_AVAILABLE)) {
998                         gchar *subject, *msg, *format = NULL;
999                         TnyAccount *account;
1000
1001                         subject = (header) ? tny_header_dup_subject (header) : NULL;
1002                         if (!subject)
1003                                 subject = g_strdup (_("mail_va_no_subject"));
1004
1005                         account = modest_mail_operation_get_account (mail_op);
1006                         if (account) {
1007                                 ModestProtocolType proto = modest_tny_account_get_protocol_type (account);
1008                                 ModestProtocol *protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (), proto);
1009
1010                                 if (protocol) {
1011                                         if (tny_account_get_connection_status (account) ==
1012                                             TNY_CONNECTION_STATUS_CONNECTED) {
1013                                                 format = modest_protocol_get_translation (protocol,
1014                                                                                           MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE,
1015                                                                                           subject);
1016                                         } else {
1017                                                 format = g_strdup_printf (_("mail_ib_backend_server_invalid"),
1018                                                                           tny_account_get_hostname (account));
1019                                         }
1020                                 }
1021                                 g_object_unref (account);
1022                         }
1023
1024                         if (!format)
1025                                 format = g_strdup (_("emev_ni_ui_imap_message_not_available_in_server"));
1026
1027                         msg = g_strdup_printf (format, subject);
1028                         modest_platform_run_information_dialog (NULL, msg, FALSE);
1029                         g_free (msg);
1030                         g_free (format);
1031                         g_free (subject);
1032                 }
1033
1034                 /* Remove the header from the preregistered uids */
1035                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1036                                                      header);
1037
1038                 return FALSE;
1039         }
1040
1041         return TRUE;
1042 }
1043
1044 typedef struct {
1045         guint idle_handler;
1046         gchar *message;
1047         GtkWidget *banner;
1048 } OpenMsgBannerInfo;
1049
1050 typedef struct {
1051         GtkTreeModel *model;
1052         TnyHeader *header;
1053         ModestWindow *caller_window;
1054         OpenMsgBannerInfo *banner_info;
1055         GtkTreeRowReference *rowref;
1056 } OpenMsgHelper;
1057
1058 gboolean
1059 open_msg_banner_idle (gpointer userdata)
1060 {
1061         OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
1062
1063         gdk_threads_enter ();
1064         banner_info->idle_handler = 0;
1065         banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
1066         if (banner_info->banner)
1067                 g_object_ref (banner_info->banner);
1068
1069         gdk_threads_leave ();
1070
1071         return FALSE;
1072 }
1073
1074 static GtkWidget *
1075 get_header_view_from_window (ModestWindow *window)
1076 {
1077         GtkWidget *header_view;
1078
1079 #ifndef MODEST_TOOLKIT_HILDON2
1080         if (MODEST_IS_MAIN_WINDOW (window)) {
1081                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
1082                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1083 #else
1084         if (MODEST_IS_HEADER_WINDOW (window)){
1085                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
1086 #endif
1087         } else {
1088                 header_view = NULL;
1089         }
1090
1091         return header_view;
1092 }
1093
1094 static gchar *
1095 get_info_from_header (TnyHeader *header, gboolean *is_draft, gboolean *can_open)
1096 {
1097         TnyFolder *folder;
1098         gchar *account = NULL;
1099         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
1100
1101         *is_draft = FALSE;
1102         *can_open = TRUE;
1103
1104         folder = tny_header_get_folder (header);
1105         /* Gets folder type (OUTBOX headers will be opened in edit window */
1106         if (modest_tny_folder_is_local_folder (folder)) {
1107                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1108                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
1109                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1110         }
1111
1112         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
1113                 TnyTransportAccount *traccount = NULL;
1114                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
1115                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
1116                 if (traccount) {
1117                         ModestTnySendQueue *send_queue = NULL;
1118                         ModestTnySendQueueStatus status;
1119                         gchar *msg_id;
1120                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
1121                                                    TNY_ACCOUNT(traccount)));
1122                         send_queue = modest_runtime_get_send_queue(traccount, TRUE);
1123                         if (TNY_IS_SEND_QUEUE (send_queue)) {
1124                                 msg_id = modest_tny_send_queue_get_msg_id (header);
1125                                 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
1126                                 g_free (msg_id);
1127                                 /* Only open messages in outbox with the editor if they are in Failed state */
1128                                 if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
1129                                         *is_draft = TRUE;
1130                                 }
1131 #ifdef MODEST_TOOLKIT_HILDON2
1132                                 else {
1133                                         /* In Fremantle we can not
1134                                            open any message from
1135                                            outbox which is not in
1136                                            failed state */
1137                                         *can_open = FALSE;
1138                                 }
1139 #endif
1140                         }
1141                         g_object_unref(traccount);
1142                 } else {
1143                         g_warning("Cannot get transport account for message in outbox!!");
1144                 }
1145         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
1146                 *is_draft = TRUE; /* Open in editor if the message is in the Drafts folder */
1147         }
1148
1149         if (!account) {
1150                 TnyAccount *acc = tny_folder_get_account (folder);
1151                 if (acc) {
1152                         account =
1153                                 g_strdup (modest_tny_account_get_parent_modest_account_name_for_server_account (acc));
1154                         g_object_unref (acc);
1155                 }
1156         }
1157
1158         g_object_unref (folder);
1159
1160         return account;
1161 }
1162
1163 static void
1164 open_msg_cb (ModestMailOperation *mail_op,
1165              TnyHeader *header,
1166              gboolean canceled,
1167              TnyMsg *msg,
1168              GError *err,
1169              gpointer user_data)
1170 {
1171         ModestWindowMgr *mgr = NULL;
1172         ModestWindow *parent_win = NULL;
1173         ModestWindow *win = NULL;
1174         gchar *account = NULL;
1175         gboolean open_in_editor = FALSE;
1176         gboolean can_open;
1177         OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1178
1179         /* Do nothing if there was any problem with the mail
1180            operation. The error will be shown by the error_handler of
1181            the mail operation */
1182         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1183                 return;
1184
1185         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
1186
1187         /* Mark header as read */
1188         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
1189
1190         account = get_info_from_header (header, &open_in_editor, &can_open);
1191
1192         /* Get account */
1193         if (!account)
1194                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
1195         if (!account)
1196                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1197
1198         if (open_in_editor) {
1199                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
1200                 gchar *from_header = NULL, *acc_name;
1201                 gchar *mailbox = NULL;
1202
1203                 from_header = tny_header_dup_from (header);
1204
1205                 /* we cannot edit without a valid account... */
1206                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
1207                         if (!modest_ui_actions_run_account_setup_wizard(parent_win)) {
1208                                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1209                                                                      header);
1210                                 g_free (from_header);
1211                                 goto cleanup;
1212                         }
1213                 }
1214
1215                 acc_name = modest_utils_get_account_name_from_recipient (from_header, &mailbox);
1216                 g_free (from_header);
1217                 if (acc_name) {
1218                         g_free (account);
1219                         account = acc_name;
1220                 }
1221
1222                 win = modest_msg_edit_window_new (msg, account, mailbox, TRUE);
1223                 if (mailbox)
1224                         g_free (mailbox);
1225         } else {
1226                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
1227                 const gchar *mailbox = NULL;
1228
1229                 if (parent_win && MODEST_IS_WINDOW (parent_win))
1230                         mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_win));
1231
1232                 if (helper->rowref && helper->model) {
1233                         win = modest_msg_view_window_new_with_header_model (msg, account, mailbox, (const gchar*) uid,
1234                                                                             helper->model, helper->rowref);
1235                 } else {
1236                         win = modest_msg_view_window_new_for_attachment (msg, account, mailbox, (const gchar*) uid);
1237                 }
1238                 g_free (uid);
1239         }
1240
1241         /* Register and show new window */
1242         if (win != NULL) {
1243                 mgr = modest_runtime_get_window_mgr ();
1244                 if (!modest_window_mgr_register_window (mgr, win, NULL)) {
1245                         gtk_widget_destroy (GTK_WIDGET (win));
1246                         goto cleanup;
1247                 }
1248                 gtk_widget_show_all (GTK_WIDGET(win));
1249         }
1250
1251 #ifndef MODEST_TOOLKIT_HILDON2
1252         /* Update toolbar dimming state */
1253         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
1254                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1255         }
1256 #endif
1257
1258 cleanup:
1259         /* Free */
1260         g_free(account);
1261         g_object_unref (parent_win);
1262 }
1263
1264 void
1265 modest_ui_actions_disk_operations_error_handler (ModestMailOperation *mail_op,
1266                                                  gpointer user_data)
1267 {
1268         const GError *error;
1269         GObject *win = NULL;
1270         ModestMailOperationStatus status;
1271
1272         win = modest_mail_operation_get_source (mail_op);
1273         error = modest_mail_operation_get_error (mail_op);
1274         status = modest_mail_operation_get_status (mail_op);
1275
1276         /* If the mail op has been cancelled then it's not an error:
1277            don't show any message */
1278         if (status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1279                 TnyAccount *account = modest_mail_operation_get_account (mail_op);
1280                 if (modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
1281                                                                  (GError *) error, account)) {
1282                         gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
1283                         modest_platform_information_banner ((GtkWidget *) win, NULL, msg);
1284                         g_free (msg);
1285                 } else if (error->code == TNY_SYSTEM_ERROR_MEMORY) {
1286                         modest_platform_information_banner ((GtkWidget *) win,
1287                                                             NULL, _("emev_ui_imap_inbox_select_error"));
1288                 } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
1289                            error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1290                         modest_platform_information_banner ((GtkWidget *) win,
1291                                                             NULL, _CS ("sfil_ni_unable_to_open_file_not_found"));
1292                 } else if (user_data) {
1293                         modest_platform_information_banner ((GtkWidget *) win,
1294                                                             NULL, user_data);
1295                 }
1296                 if (account)
1297                         g_object_unref (account);
1298         }
1299
1300         if (win)
1301                 g_object_unref (win);
1302 }
1303
1304 /**
1305  * Returns the account a list of headers belongs to. It returns a
1306  * *new* reference so don't forget to unref it
1307  */
1308 static TnyAccount*
1309 get_account_from_header_list (TnyList *headers)
1310 {
1311         TnyAccount *account = NULL;
1312
1313         if (tny_list_get_length (headers) > 0) {
1314                 TnyIterator *iter = tny_list_create_iterator (headers);
1315                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1316                 TnyFolder *folder = tny_header_get_folder (header);
1317
1318                 if (!folder) {
1319                         g_object_unref (header);
1320
1321                         while (!tny_iterator_is_done (iter)) {
1322                                 header = TNY_HEADER (tny_iterator_get_current (iter));
1323                                 folder = tny_header_get_folder (header);
1324                                 if (folder)
1325                                         break;
1326                                 g_object_unref (header);
1327                                 header = NULL;
1328                                 tny_iterator_next (iter);
1329                         }
1330                 }
1331
1332                 if (folder) {
1333                         account = tny_folder_get_account (folder);
1334                         g_object_unref (folder);
1335                 }
1336
1337                 if (header)
1338                         g_object_unref (header);
1339
1340                 g_object_unref (iter);
1341         }
1342         return account;
1343 }
1344
1345 static TnyAccount*
1346 get_account_from_header (TnyHeader *header)
1347 {
1348         TnyAccount *account = NULL;
1349         TnyFolder *folder;
1350
1351         folder = tny_header_get_folder (header);
1352
1353         if (folder) {
1354                 account = tny_folder_get_account (folder);
1355                 g_object_unref (folder);
1356         }
1357         return account;
1358 }
1359
1360 static void
1361 caller_win_destroyed (OpenMsgHelper *helper, GObject *object)
1362 {
1363         if (helper->caller_window)
1364                 helper->caller_window = NULL;
1365 }
1366
1367 static void
1368 open_msg_helper_destroyer (gpointer user_data)
1369 {
1370         OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1371
1372         if (helper->caller_window) {
1373                 g_object_weak_unref ((GObject *) helper->caller_window, (GWeakNotify) caller_win_destroyed, helper);
1374                 helper->caller_window = NULL;
1375         }
1376
1377         if (helper->banner_info) {
1378                 g_free (helper->banner_info->message);
1379                 if (helper->banner_info->idle_handler > 0) {
1380                         g_source_remove (helper->banner_info->idle_handler);
1381                         helper->banner_info->idle_handler = 0;
1382                 }
1383                 if (helper->banner_info->banner != NULL) {
1384                         gtk_widget_destroy (helper->banner_info->banner);
1385                         g_object_unref (helper->banner_info->banner);
1386                         helper->banner_info->banner = NULL;
1387                 }
1388                 g_slice_free (OpenMsgBannerInfo, helper->banner_info);
1389                 helper->banner_info = NULL;
1390         }
1391         g_object_unref (helper->model);
1392         g_object_unref (helper->header);
1393         gtk_tree_row_reference_free (helper->rowref);
1394         g_slice_free (OpenMsgHelper, helper);
1395 }
1396
1397 static void
1398 open_msg_performer(gboolean canceled,
1399                     GError *err,
1400                     GtkWindow *parent_window,
1401                     TnyAccount *account,
1402                     gpointer user_data)
1403 {
1404         ModestMailOperation *mail_op = NULL;
1405         gchar *error_msg = NULL;
1406         ModestProtocolType proto;
1407         TnyConnectionStatus status;
1408         OpenMsgHelper *helper = NULL;
1409         ModestProtocol *protocol;
1410         ModestProtocolRegistry *protocol_registry;
1411         gchar *subject;
1412
1413         helper = (OpenMsgHelper *) user_data;
1414
1415         status = tny_account_get_connection_status (account);
1416         if (err || canceled || helper->caller_window == NULL) {
1417                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1418                 /* Free the helper */
1419                 open_msg_helper_destroyer (helper);
1420
1421                 /* In disk full conditions we could get this error here */
1422                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
1423                                                                 (GtkWidget *) parent_window, err,
1424                                                                 account, NULL);
1425
1426                 goto clean;
1427         }
1428
1429         /* Get the error message depending on the protocol */
1430         proto = modest_tny_account_get_protocol_type (account);
1431         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
1432                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
1433         }
1434
1435         protocol_registry = modest_runtime_get_protocol_registry ();
1436         subject = tny_header_dup_subject (helper->header);
1437
1438         protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, proto);
1439         error_msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
1440         if (subject)
1441                 g_free (subject);
1442
1443         if (error_msg == NULL) {
1444                 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1445         }
1446
1447 #ifndef MODEST_TOOLKIT_HILDON2
1448         gboolean show_open_draft = FALSE;
1449         if (modest_protocol_registry_protocol_type_has_tag (protocol_registry,
1450                                                             proto,
1451                                                             MODEST_PROTOCOL_REGISTRY_LOCAL_STORE_PROTOCOLS)) {
1452                 TnyFolder *folder;
1453                 TnyFolderType folder_type;
1454
1455                 folder = tny_header_get_folder (helper->header);
1456                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1457                 show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1458                 g_object_unref (folder);
1459         }
1460 #endif
1461
1462 #ifdef MODEST_TOOLKIT_HILDON2
1463         gboolean is_draft;
1464         gboolean can_open;
1465         gchar *account_name = get_info_from_header (helper->header, &is_draft, &can_open);
1466
1467         if (!can_open) {
1468                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1469                 g_free (account_name);
1470                 open_msg_helper_destroyer (helper);
1471                 goto clean;
1472         }
1473
1474         if (!is_draft) {
1475                 ModestWindow *window;
1476                 GtkWidget *header_view;
1477                 gchar *uid;
1478
1479                 header_view = get_header_view_from_window (MODEST_WINDOW (parent_window));
1480                 uid = modest_tny_folder_get_header_unique_id (helper->header);
1481                 if (header_view) {
1482                         const gchar *mailbox = NULL;
1483                         mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_window));
1484                         window = modest_msg_view_window_new_from_header_view 
1485                                 (MODEST_HEADER_VIEW (header_view), account_name, mailbox, uid, helper->rowref);
1486                         if (window != NULL) {
1487                                 if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr (),
1488                                                                         window, NULL)) {
1489                                         gtk_widget_destroy (GTK_WIDGET (window));
1490                                 } else {
1491                                         gtk_widget_show_all (GTK_WIDGET(window));
1492                                 }
1493                         }
1494                 }
1495                 g_free (account_name);
1496                 g_free (uid);
1497                 open_msg_helper_destroyer (helper);
1498                 goto clean;
1499         }
1500         g_free (account_name);
1501 #endif
1502         /* Create the mail operation */
1503         mail_op =
1504                 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1505                                                                modest_ui_actions_disk_operations_error_handler,
1506                                                                g_strdup (error_msg), g_free);
1507         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1508                                          mail_op);
1509
1510
1511 #ifndef MODEST_TOOLKIT_HILDON2
1512         if (show_open_draft) {
1513                 helper->banner_info = g_slice_new (OpenMsgBannerInfo);
1514                 helper->banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1515                 helper->banner_info->banner = NULL;
1516                 helper->banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle,
1517                                                                    helper->banner_info);
1518         }
1519 #endif
1520
1521
1522         TnyList *headers;
1523         headers = TNY_LIST (tny_simple_list_new ());
1524         tny_list_prepend (headers, G_OBJECT (helper->header));
1525         modest_mail_operation_get_msgs_full (mail_op,
1526                                              headers,
1527                                              open_msg_cb,
1528                                              helper,
1529                                              open_msg_helper_destroyer);
1530         g_object_unref (headers);
1531
1532         /* Frees */
1533  clean:
1534         if (error_msg)
1535                 g_free (error_msg);
1536         if (mail_op)
1537                 g_object_unref (mail_op);
1538         g_object_unref (account);
1539 }
1540
1541 /*
1542  * This function is used by both modest_ui_actions_on_open and
1543  * modest_ui_actions_on_header_activated. This way we always do the
1544  * same when trying to open messages.
1545  */
1546 static void
1547 open_msg_from_header (TnyHeader *header, GtkTreeRowReference *rowref, ModestWindow *win)
1548 {
1549         ModestWindowMgr *mgr = NULL;
1550         TnyAccount *account;
1551         gboolean cached = FALSE;
1552         gboolean found;
1553         GtkWidget *header_view = NULL;
1554         OpenMsgHelper *helper;
1555         ModestWindow *window;
1556
1557         g_return_if_fail (header != NULL && rowref != NULL && gtk_tree_row_reference_valid (rowref));
1558
1559         mgr = modest_runtime_get_window_mgr ();
1560
1561         /* get model */
1562         header_view = get_header_view_from_window (MODEST_WINDOW (win));
1563         if (header_view == NULL)
1564                 return;
1565
1566         /* Get the account */
1567         account = get_account_from_header (header);
1568         if (!account)
1569                 return;
1570
1571         window = NULL;
1572         found = modest_window_mgr_find_registered_header (mgr, header, &window);
1573
1574         /* Do not open again the message and present the
1575            window to the user */
1576         if (found) {
1577                 if (window) {
1578 #ifndef MODEST_TOOLKIT_HILDON2
1579                         gtk_window_present (GTK_WINDOW (window));
1580 #endif
1581                 } else {
1582                         /* the header has been registered already, we don't do
1583                          * anything but wait for the window to come up*/
1584                         g_debug ("header %p already registered, waiting for window", header);
1585                 }
1586                 goto cleanup;
1587         }
1588
1589         /* Open each message */
1590         cached = tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED;
1591         if (!cached) {
1592                 /* Allways download if we are online. */
1593                 if (!tny_device_is_online (modest_runtime_get_device ())) {
1594                         gint response;
1595
1596                         /* If ask for user permission to download the messages */
1597                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1598                                                                             _("mcen_nc_get_msg"));
1599
1600                         /* End if the user does not want to continue */
1601                         if (response == GTK_RESPONSE_CANCEL) {
1602                                 goto cleanup;
1603                         }
1604                 }
1605         }
1606
1607         /* We register the window for opening */
1608         modest_window_mgr_register_header (mgr, header, NULL);
1609
1610         /* Create the helper. We need to get a reference to the model
1611            here because it could change while the message is readed
1612            (the user could switch between folders) */
1613         helper = g_slice_new (OpenMsgHelper);
1614         helper->model = g_object_ref (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
1615         helper->caller_window = win;
1616         g_object_weak_ref ((GObject *) helper->caller_window, (GWeakNotify) caller_win_destroyed, helper);
1617         helper->header = g_object_ref (header);
1618         helper->rowref = gtk_tree_row_reference_copy (rowref);
1619         helper->banner_info = NULL;
1620
1621         /* Connect to the account and perform */
1622         if (!cached) {
1623                 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account),
1624                                                      open_msg_performer, helper);
1625         } else {
1626                 /* Call directly the performer, do not need to connect */
1627                 open_msg_performer (FALSE, NULL, (GtkWindow *) win,
1628                                     g_object_ref (account), helper);
1629         }
1630 cleanup:
1631         /* Clean */
1632         if (account)
1633                 g_object_unref (account);
1634 }
1635
1636 void
1637 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1638 {
1639         TnyList *headers;
1640         TnyHeader *header;
1641         gint headers_count;
1642         TnyIterator *iter;
1643
1644         /* we check for low-mem; in that case, show a warning, and don't allow
1645          * opening
1646          */
1647         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1648                 return;
1649
1650         /* Get headers */
1651         headers = get_selected_headers (win);
1652         if (!headers)
1653                 return;
1654
1655         headers_count = tny_list_get_length (headers);
1656         if (headers_count != 1) {
1657                 if (headers_count > 1) {
1658                         /* Don't allow activation if there are more than one message selected */
1659                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
1660                 }
1661
1662                 g_object_unref (headers);
1663                 return;
1664         }
1665
1666         iter = tny_list_create_iterator (headers);
1667         header = TNY_HEADER (tny_iterator_get_current (iter));
1668         g_object_unref (iter);
1669
1670         /* Open them */
1671         if (header) {
1672                 open_msg_from_header (header, NULL, win);
1673                 g_object_unref (header);
1674         }
1675
1676         g_object_unref(headers);
1677 }
1678
1679 static void
1680 rf_helper_window_closed (gpointer data,
1681                          GObject *object)
1682 {
1683         ReplyForwardHelper *helper = (ReplyForwardHelper *) data;
1684
1685         helper->parent_window = NULL;
1686 }
1687
1688 static ReplyForwardHelper*
1689 create_reply_forward_helper (ReplyForwardAction action,
1690                              ModestWindow *win,
1691                              guint reply_forward_type,
1692                              TnyHeader *header)
1693 {
1694         ReplyForwardHelper *rf_helper = NULL;
1695         const gchar *active_acc = modest_window_get_active_account (win);
1696         const gchar *active_mailbox = modest_window_get_active_mailbox (win);
1697
1698         rf_helper = g_slice_new0 (ReplyForwardHelper);
1699         rf_helper->reply_forward_type = reply_forward_type;
1700         rf_helper->action = action;
1701         rf_helper->parent_window = (MODEST_IS_WINDOW (win)) ? GTK_WIDGET (win) : NULL;
1702         rf_helper->header = (header) ? g_object_ref (header) : NULL;
1703         rf_helper->account_name = (active_acc) ?
1704                 g_strdup (active_acc) :
1705                 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1706         rf_helper->mailbox = g_strdup (active_mailbox);
1707
1708         /* Note that window could be destroyed just AFTER calling
1709            register_window so we must ensure that this pointer does
1710            not hold invalid references */
1711         if (rf_helper->parent_window)
1712                 g_object_weak_ref (G_OBJECT (rf_helper->parent_window),
1713                                    rf_helper_window_closed, rf_helper);
1714
1715         return rf_helper;
1716 }
1717
1718 static void
1719 free_reply_forward_helper (gpointer data)
1720 {
1721         ReplyForwardHelper *helper;
1722
1723         helper = (ReplyForwardHelper *) data;
1724         g_free (helper->account_name);
1725         g_free (helper->mailbox);
1726         if (helper->header)
1727                 g_object_unref (helper->header);
1728         if (helper->parent_window)
1729                 g_object_weak_unref (G_OBJECT (helper->parent_window),
1730                                      rf_helper_window_closed, helper);
1731         g_slice_free (ReplyForwardHelper, helper);
1732 }
1733
1734 static void
1735 reply_forward_cb (ModestMailOperation *mail_op,
1736                   TnyHeader *header,
1737                   gboolean canceled,
1738                   TnyMsg *msg,
1739                   GError *err,
1740                   gpointer user_data)
1741 {
1742         TnyMsg *new_msg = NULL;
1743         ReplyForwardHelper *rf_helper;
1744         ModestWindow *msg_win = NULL;
1745         ModestEditType edit_type;
1746         gchar *from = NULL;
1747         TnyAccount *account = NULL;
1748         ModestWindowMgr *mgr = NULL;
1749         gchar *signature = NULL;
1750         gboolean use_signature;
1751         gchar *recipient;
1752
1753         /* If there was any error. The mail operation could be NULL,
1754            this means that we already have the message downloaded and
1755            that we didn't do a mail operation to retrieve it */
1756         rf_helper = (ReplyForwardHelper *) user_data;
1757         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1758                 goto cleanup;
1759
1760         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1761                                                    rf_helper->account_name, rf_helper->mailbox);
1762         recipient = modest_text_utils_get_email_address (from);
1763         signature = modest_account_mgr_get_signature_from_recipient (modest_runtime_get_account_mgr(), 
1764                                                                      recipient, 
1765                                                                      &use_signature);
1766         g_free (recipient);
1767
1768         /* Create reply mail */
1769         switch (rf_helper->action) {
1770                 /* Use the msg_header to ensure that we have all the
1771                    information. The summary can lack some data */
1772                 TnyHeader *msg_header;
1773         case ACTION_REPLY:
1774                 msg_header = tny_msg_get_header (msg);
1775                 new_msg =
1776                         modest_tny_msg_create_reply_msg (msg, msg_header, from,
1777                                                          (use_signature) ? signature : NULL,
1778                                                          rf_helper->reply_forward_type,
1779                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1780                 g_object_unref (msg_header);
1781                 break;
1782         case ACTION_REPLY_TO_ALL:
1783                 msg_header = tny_msg_get_header (msg);
1784                 new_msg =
1785                         modest_tny_msg_create_reply_msg (msg, msg_header, from,
1786                                                          (use_signature) ? signature : NULL,
1787                                                          rf_helper->reply_forward_type,
1788                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1789                 edit_type = MODEST_EDIT_TYPE_REPLY;
1790                 g_object_unref (msg_header);
1791                 break;
1792         case ACTION_FORWARD:
1793                 new_msg =
1794                         modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL,
1795                                                            rf_helper->reply_forward_type);
1796                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1797                 break;
1798         default:
1799                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1800                                                      header);
1801                 g_return_if_reached ();
1802                 return;
1803         }
1804
1805         g_free (from);
1806         g_free (signature);
1807
1808         if (!new_msg) {
1809                 g_warning ("%s: failed to create message\n", __FUNCTION__);
1810                 goto cleanup;
1811         }
1812
1813         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1814                                                                        rf_helper->account_name,
1815                                                                        TNY_ACCOUNT_TYPE_STORE);
1816         if (!account) {
1817                 g_warning ("%s: failed to get tnyaccount for '%s'\n", __FUNCTION__, rf_helper->account_name);
1818                 goto cleanup;
1819         }
1820
1821         /* Create and register the windows */
1822         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, rf_helper->mailbox, FALSE);
1823         mgr = modest_runtime_get_window_mgr ();
1824         modest_window_mgr_register_window (mgr, msg_win, (ModestWindow *) rf_helper->parent_window);
1825
1826         /* Note that register_window could have deleted the account */
1827         if (MODEST_IS_WINDOW (rf_helper->parent_window)) {
1828                 gdouble parent_zoom;
1829
1830                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1831                 modest_window_set_zoom (msg_win, parent_zoom);
1832         }
1833
1834         /* Show edit window */
1835         gtk_widget_show_all (GTK_WIDGET (msg_win));
1836
1837 cleanup:
1838         /* We always unregister the header because the message is
1839            forwarded or replied so the original one is no longer
1840            opened */
1841         modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1842                                              header);
1843         if (new_msg)
1844                 g_object_unref (G_OBJECT (new_msg));
1845         if (account)
1846                 g_object_unref (G_OBJECT (account));
1847         free_reply_forward_helper (rf_helper);
1848 }
1849
1850 /* Checks a list of headers. If any of them are not currently
1851  * downloaded (CACHED) then returns TRUE else returns FALSE.
1852  */
1853 static gint
1854 header_list_count_uncached_msgs (TnyList *header_list)
1855 {
1856         TnyIterator *iter;
1857         gint uncached_messages = 0;
1858
1859         iter = tny_list_create_iterator (header_list);
1860         while (!tny_iterator_is_done (iter)) {
1861                 TnyHeader *header;
1862
1863                 header = TNY_HEADER (tny_iterator_get_current (iter));
1864                 if (header) {
1865                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1866                                 uncached_messages ++;
1867                         g_object_unref (header);
1868                 }
1869
1870                 tny_iterator_next (iter);
1871         }
1872         g_object_unref (iter);
1873
1874         return uncached_messages;
1875 }
1876
1877 /* Returns FALSE if the user does not want to download the
1878  * messages. Returns TRUE if the user allowed the download.
1879  */
1880 static gboolean
1881 connect_to_get_msg (ModestWindow *win,
1882                     gint num_of_uncached_msgs,
1883                     TnyAccount *account)
1884 {
1885         GtkResponseType response;
1886
1887         /* Allways download if we are online. */
1888         if (tny_device_is_online (modest_runtime_get_device ()))
1889                 return TRUE;
1890
1891         /* If offline, then ask for user permission to download the messages */
1892         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1893                         ngettext("mcen_nc_get_msg",
1894                         "mcen_nc_get_msgs",
1895                         num_of_uncached_msgs));
1896
1897         if (response == GTK_RESPONSE_CANCEL)
1898                 return FALSE;
1899
1900         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1901 }
1902
1903 static void
1904 reply_forward_performer (gboolean canceled,
1905                          GError *err,
1906                          GtkWindow *parent_window,
1907                          TnyAccount *account,
1908                          gpointer user_data)
1909 {
1910         ReplyForwardHelper *rf_helper = NULL;
1911         ModestMailOperation *mail_op;
1912
1913         rf_helper = (ReplyForwardHelper *) user_data;
1914
1915         if (canceled || err) {
1916                 free_reply_forward_helper (rf_helper);
1917                 return;
1918         }
1919
1920         /* Retrieve the message */
1921         modest_window_mgr_register_header (modest_runtime_get_window_mgr (), rf_helper->header, NULL);
1922         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (parent_window),
1923                                                                  modest_ui_actions_disk_operations_error_handler,
1924                                                                  NULL, NULL);
1925         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1926         modest_mail_operation_get_msg (mail_op, rf_helper->header, TRUE, reply_forward_cb, rf_helper);
1927
1928         /* Frees */
1929         g_object_unref(mail_op);
1930 }
1931
1932 /*
1933  * Common code for the reply and forward actions
1934  */
1935 static void
1936 reply_forward (ReplyForwardAction action, ModestWindow *win)
1937 {
1938         ReplyForwardHelper *rf_helper = NULL;
1939         guint reply_forward_type;
1940
1941         g_return_if_fail (win && MODEST_IS_WINDOW(win));
1942
1943         /* we check for low-mem; in that case, show a warning, and don't allow
1944          * reply/forward (because it could potentially require a lot of memory */
1945         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1946                 return;
1947
1948
1949         /* we need an account when editing */
1950         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1951                 if (!modest_ui_actions_run_account_setup_wizard (win))
1952                         return;
1953         }
1954
1955         reply_forward_type =
1956                 modest_conf_get_int (modest_runtime_get_conf (),
1957                                      (action == ACTION_FORWARD) ?
1958                                      MODEST_CONF_FORWARD_TYPE :
1959                                      MODEST_CONF_REPLY_TYPE,
1960                                      NULL);
1961
1962         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1963                 TnyMsg *msg = NULL;
1964                 TnyHeader *header = NULL;
1965                 /* Get header and message. Do not free them here, the
1966                    reply_forward_cb must do it */
1967                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1968                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
1969
1970                 if (msg && header) {
1971                         /* Create helper */
1972                         rf_helper = create_reply_forward_helper (action, win,
1973                                                                  reply_forward_type, header);
1974                         reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1975                 } else {
1976                         g_warning("%s: no message or header found in viewer\n", __FUNCTION__);
1977                 }
1978
1979                 if (msg)
1980                         g_object_unref (msg);
1981                 if (header)
1982                         g_object_unref (header);
1983         } else {
1984                 TnyHeader *header = NULL;
1985                 TnyIterator *iter;
1986                 gboolean do_retrieve = TRUE;
1987                 TnyList *header_list = NULL;
1988
1989                 header_list = get_selected_headers (win);
1990                 if (!header_list)
1991                         return;
1992                 /* Check that only one message is selected for replying */
1993                 if (tny_list_get_length (header_list) != 1) {
1994                         modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1995                                                             NULL, _("mcen_ib_select_one_message"));
1996                         g_object_unref (header_list);
1997                         return;
1998                 }
1999
2000                 /* Only reply/forward to one message */
2001                 iter = tny_list_create_iterator (header_list);
2002                 header = TNY_HEADER (tny_iterator_get_current (iter));
2003                 g_object_unref (iter);
2004
2005                 /* Retrieve messages */
2006                 do_retrieve = (action == ACTION_FORWARD) ||
2007                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
2008
2009                 if (do_retrieve) {
2010                         TnyAccount *account = NULL;
2011                         TnyFolder *folder = NULL;
2012                         gdouble download = TRUE;
2013                         guint uncached_msgs = 0;
2014
2015                         folder = tny_header_get_folder (header);
2016                         if (!folder)
2017                                 goto do_retrieve_frees;
2018                         account = tny_folder_get_account (folder);
2019                         if (!account)
2020                                 goto do_retrieve_frees;
2021
2022                         uncached_msgs = header_list_count_uncached_msgs (header_list);
2023
2024                         if (uncached_msgs > 0) {
2025                                 /* Allways download if we are online. */
2026                                 if (!tny_device_is_online (modest_runtime_get_device ())) {
2027                                         gint response;
2028
2029                                         /* If ask for user permission to download the messages */
2030                                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2031                                                                                             ngettext("mcen_nc_get_msg",
2032                                                                                                      "mcen_nc_get_msgs",
2033                                                                                                      uncached_msgs));
2034
2035                                         /* End if the user does not want to continue */
2036                                         if (response == GTK_RESPONSE_CANCEL)
2037                                                 download = FALSE;
2038                                 }
2039                         }
2040
2041                         if (download) {
2042                                 /* Create helper */
2043                                 rf_helper = create_reply_forward_helper (action, win,
2044                                                                          reply_forward_type, header);
2045                                 if (uncached_msgs > 0) {
2046                                         modest_platform_connect_and_perform (GTK_WINDOW (win),
2047                                                                              TRUE, account,
2048                                                                              reply_forward_performer,
2049                                                                              rf_helper);
2050                                 } else {
2051                                         reply_forward_performer (FALSE, NULL, GTK_WINDOW (win),
2052                                                                  account, rf_helper);
2053                                 }
2054                         }
2055                 do_retrieve_frees:
2056                         if (account)
2057                                 g_object_unref (account);
2058                         if (folder)
2059                                 g_object_unref (folder);
2060                 } else {
2061                         reply_forward_cb (NULL, header, FALSE, NULL, NULL, NULL);
2062                 }
2063                 /* Frees */
2064                 g_object_unref (header_list);
2065                 g_object_unref (header);
2066         }
2067 }
2068
2069 void
2070 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
2071 {
2072         g_return_if_fail (MODEST_IS_WINDOW(win));
2073
2074         reply_forward (ACTION_REPLY, win);
2075 }
2076
2077 void
2078 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
2079 {
2080         g_return_if_fail (MODEST_IS_WINDOW(win));
2081
2082         reply_forward (ACTION_FORWARD, win);
2083 }
2084
2085 void
2086 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
2087 {
2088         g_return_if_fail (MODEST_IS_WINDOW(win));
2089
2090         reply_forward (ACTION_REPLY_TO_ALL, win);
2091 }
2092
2093 void
2094 modest_ui_actions_on_next (GtkAction *action,
2095                            ModestWindow *window)
2096 {
2097 #ifndef MODEST_TOOLKIT_HILDON2
2098         if (MODEST_IS_MAIN_WINDOW (window)) {
2099                 GtkWidget *header_view;
2100
2101                 header_view = modest_main_window_get_child_widget (
2102                                 MODEST_MAIN_WINDOW(window),
2103                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2104                 if (!header_view)
2105                         return;
2106
2107                 modest_header_view_select_next (
2108                                 MODEST_HEADER_VIEW(header_view));
2109 #else
2110         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2111                 modest_msg_view_window_select_next_message (
2112                                 MODEST_MSG_VIEW_WINDOW (window));
2113 #endif
2114         } else {
2115                 g_return_if_reached ();
2116         }
2117 }
2118
2119 void
2120 modest_ui_actions_on_prev (GtkAction *action,
2121                            ModestWindow *window)
2122 {
2123         g_return_if_fail (MODEST_IS_WINDOW(window));
2124
2125 #ifndef MODEST_TOOLKIT_HILDON2
2126         if (MODEST_IS_MAIN_WINDOW (window)) {
2127                 GtkWidget *header_view;
2128                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2129                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2130                 if (!header_view)
2131                         return;
2132
2133                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
2134 #else
2135         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2136                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
2137 #endif
2138         } else {
2139                 g_return_if_reached ();
2140         }
2141 }
2142
2143 void
2144 modest_ui_actions_on_sort (GtkAction *action,
2145                            ModestWindow *window)
2146 {
2147         GtkWidget *header_view = NULL;
2148
2149         g_return_if_fail (MODEST_IS_WINDOW(window));
2150
2151 #ifndef MODEST_TOOLKIT_HILDON2
2152         if (MODEST_IS_MAIN_WINDOW (window)) {
2153                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2154                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2155 #else
2156         if (MODEST_IS_HEADER_WINDOW (window)) {
2157                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
2158 #endif
2159         }
2160
2161         if (!header_view) {
2162                 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
2163
2164                 return;
2165         }
2166
2167         /* Show sorting dialog */
2168         modest_utils_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
2169 }
2170
2171 static void
2172 sync_folder_cb (ModestMailOperation *mail_op,
2173                 TnyFolder *folder,
2174                 gpointer user_data)
2175 {
2176         ModestHeaderView *header_view = (ModestHeaderView *) user_data;
2177
2178         if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
2179                 ModestWindow *parent = (ModestWindow *) modest_mail_operation_get_source (mail_op);
2180
2181                 /* We must clear first, because otherwise set_folder will ignore */
2182                 /*    the change as the folders are the same */
2183                 modest_header_view_clear (header_view);
2184                 modest_header_view_set_folder (header_view, folder, TRUE, parent, NULL, NULL);
2185
2186                 g_object_unref (parent);
2187         }
2188
2189         g_object_unref (header_view);
2190 }
2191
2192 static gboolean
2193 idle_refresh_folder (gpointer source)
2194 {
2195         ModestHeaderView *header_view = NULL;
2196
2197         /* If the window still exists */
2198         if (!GTK_IS_WIDGET (source) ||
2199             !GTK_WIDGET_VISIBLE (source))
2200                 return FALSE;
2201
2202         /* Refresh the current view */
2203 #ifdef MODEST_TOOLKIT_HILDON2
2204         if (MODEST_IS_HEADER_WINDOW (source))
2205                 header_view = modest_header_window_get_header_view ((ModestHeaderWindow *) source);
2206 #else
2207         if (MODEST_IS_MAIN_WINDOW (source))
2208                 header_view = MODEST_HEADER_VIEW (modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source),
2209                                                                                        MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
2210 #endif
2211         if (header_view) {
2212                 TnyFolder *folder = modest_header_view_get_folder (header_view);
2213                 if (folder) {
2214                         /* Sync the folder status */
2215                         ModestMailOperation *mail_op = modest_mail_operation_new (source);
2216                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2217                         modest_mail_operation_sync_folder (mail_op, folder, FALSE, sync_folder_cb, g_object_ref (header_view));
2218                         g_object_unref (folder);
2219                         g_object_unref (mail_op);
2220                 }
2221         }
2222
2223         return FALSE;
2224 }
2225
2226 static void
2227 update_account_cb (ModestMailOperation *self,
2228                    TnyList *new_headers,
2229                    gpointer user_data)
2230 {
2231         ModestWindow *top;
2232         gboolean show_visual_notifications;
2233
2234         top = modest_window_mgr_get_current_top (modest_runtime_get_window_mgr ());
2235         show_visual_notifications = (top) ? FALSE : TRUE;
2236
2237         /* Notify new messages have been downloaded. If the
2238            send&receive was invoked by the user then do not show any
2239            visual notification, only play a sound and activate the LED
2240            (for the Maemo version) */
2241         if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0) {
2242
2243                 /* We only notify about really new messages (not seen) we get */
2244                 TnyList *actually_new_list;
2245                 TnyIterator *iterator;
2246                 actually_new_list = TNY_LIST (tny_simple_list_new ());
2247                 for (iterator = tny_list_create_iterator (new_headers);
2248                      !tny_iterator_is_done (iterator);
2249                      tny_iterator_next (iterator)) {
2250                         TnyHeader *header;
2251                         TnyHeaderFlags flags;
2252                         header = TNY_HEADER (tny_iterator_get_current (iterator));
2253                         flags = tny_header_get_flags (header);
2254
2255                         if (!(flags & TNY_HEADER_FLAG_SEEN)) {
2256                                 /* Messages are ordered from most
2257                                    recent to oldest. But we want to
2258                                    show notifications starting from
2259                                    the oldest message. That's why we
2260                                    reverse the list */
2261                                 tny_list_prepend (actually_new_list, G_OBJECT (header));
2262                         }
2263                         g_object_unref (header);
2264                 }
2265                 g_object_unref (iterator);
2266
2267                 if (tny_list_get_length (actually_new_list) > 0) {
2268                         GList *new_headers_list = NULL;
2269
2270                         new_headers_list = modest_utils_create_notification_list_from_header_list (actually_new_list);
2271
2272                         /* Send notifications */
2273                         if (new_headers_list) {
2274                                 modest_platform_on_new_headers_received (new_headers_list,
2275                                                                          show_visual_notifications);
2276                                 /* Free the list */
2277                                 modest_utils_free_notification_list (new_headers_list);
2278                         }
2279                 }
2280                 g_object_unref (actually_new_list);
2281         }
2282
2283         if (top) {
2284                 /* Refresh the current folder in an idle. We do this
2285                    in order to avoid refresh cancelations if the
2286                    currently viewed folder is the inbox */
2287                 g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
2288                                  idle_refresh_folder,
2289                                  g_object_ref (top),
2290                                  g_object_unref);
2291         }
2292 }
2293
2294 typedef struct {
2295         TnyAccount *account;
2296         ModestWindow *win;
2297         gchar *account_name;
2298         gboolean poke_status;
2299         gboolean interactive;
2300         ModestMailOperation *mail_op;
2301 } SendReceiveInfo;
2302
2303 static void
2304 do_send_receive_performer (gboolean canceled,
2305                            GError *err,
2306                            GtkWindow *parent_window,
2307                            TnyAccount *account,
2308                            gpointer user_data)
2309 {
2310         SendReceiveInfo *info;
2311
2312         info = (SendReceiveInfo *) user_data;
2313
2314         if (err || canceled) {
2315                 /* In disk full conditions we could get this error here */
2316                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
2317                                                                 (GtkWidget *) parent_window, err,
2318                                                                 account, NULL);
2319
2320                 if (info->mail_op) {
2321                         modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
2322                                                             info->mail_op);
2323                 }
2324                 goto clean;
2325         }
2326
2327 #ifndef MODEST_TOOLKIT_HILDON2
2328         /* Set send/receive operation in progress */
2329         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
2330                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
2331         }
2332
2333         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
2334                 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
2335                                   G_CALLBACK (on_send_receive_finished),
2336                                   info->win);
2337 #endif
2338
2339         /* Send & receive. */
2340         modest_mail_operation_update_account (info->mail_op, info->account_name,
2341                                               info->poke_status, info->interactive,
2342                                               update_account_cb, info->win);
2343
2344  clean:
2345         /* Frees */
2346         if (info->mail_op)
2347                 g_object_unref (G_OBJECT (info->mail_op));
2348         if (info->account_name)
2349                 g_free (info->account_name);
2350         if (info->win)
2351                 g_object_unref (info->win);
2352         if (info->account)
2353                 g_object_unref (info->account);
2354         g_slice_free (SendReceiveInfo, info);
2355 }
2356
2357 /*
2358  * This function performs the send & receive required actions. The
2359  * window is used to create the mail operation. Typically it should
2360  * always be the main window, but we pass it as argument in order to
2361  * be more flexible.
2362  */
2363 void
2364 modest_ui_actions_do_send_receive (const gchar *account_name,
2365                                    gboolean force_connection,
2366                                    gboolean poke_status,
2367                                    gboolean interactive,
2368                                    ModestWindow *win)
2369 {
2370         gchar *acc_name = NULL;
2371         SendReceiveInfo *info;
2372         ModestTnyAccountStore *acc_store;
2373         TnyAccount *account;
2374
2375         /* If no account name was provided then get the current account, and if
2376            there is no current account then pick the default one: */
2377         if (!account_name) {
2378                 if (win)
2379                         acc_name = g_strdup (modest_window_get_active_account (win));
2380                 if (!acc_name)
2381                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
2382                 if (!acc_name) {
2383                         modest_platform_information_banner (NULL, NULL, _("emev_ni_internal_error"));
2384                         return;
2385                 }
2386         } else {
2387                 acc_name = g_strdup (account_name);
2388         }
2389
2390         acc_store = modest_runtime_get_account_store ();
2391         account = modest_tny_account_store_get_server_account (acc_store, acc_name, TNY_ACCOUNT_TYPE_STORE);
2392
2393         if (!account) {
2394                 g_free (acc_name);
2395                 modest_platform_information_banner (NULL, NULL, _("emev_ni_internal_error"));
2396                 return;
2397         }
2398
2399         /* Do not automatically refresh accounts that are flagged as
2400            NO_AUTO_UPDATE. This could be useful for accounts that
2401            handle their own update times */
2402         if (!interactive) {
2403                 ModestProtocolType proto = modest_tny_account_get_protocol_type (account);
2404                 if (proto != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
2405                         const gchar *tag = MODEST_PROTOCOL_REGISTRY_NO_AUTO_UPDATE_PROTOCOLS;
2406                         ModestProtocolRegistry *registry = modest_runtime_get_protocol_registry ();
2407
2408                         if (modest_protocol_registry_protocol_type_has_tag (registry, proto, tag)) {
2409                                 g_debug ("%s no auto update allowed for account %s", __FUNCTION__, account_name);
2410                                 g_object_unref (account);
2411                                 g_free (acc_name);
2412                                 return;
2413                         }
2414                 }
2415         }
2416
2417         /* Create the info for the connect and perform */
2418         info = g_slice_new (SendReceiveInfo);
2419         info->account_name = acc_name;
2420         info->win = (win) ? g_object_ref (win) : NULL;
2421         info->poke_status = poke_status;
2422         info->interactive = interactive;
2423         info->account = account;
2424         /* We need to create the operation here, because otherwise it
2425            could happen that the queue emits the queue-empty signal
2426            while we're trying to connect the account */
2427         info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
2428                                                                        modest_ui_actions_disk_operations_error_handler,
2429                                                                        NULL, NULL);
2430         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
2431
2432         /* Invoke the connect and perform */
2433         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
2434                                              force_connection, info->account,
2435                                              do_send_receive_performer, info);
2436 }
2437
2438
2439 static void
2440 modest_ui_actions_do_cancel_send (const gchar *account_name,
2441                                   ModestWindow *win)
2442 {
2443         TnyTransportAccount *transport_account;
2444         TnySendQueue *send_queue = NULL;
2445         GError *error = NULL;
2446
2447         /* Get transport account */
2448         transport_account =
2449                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2450                                       (modest_runtime_get_account_store(),
2451                                        account_name,
2452                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2453         if (!transport_account) {
2454                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2455                 goto frees;
2456         }
2457
2458         /* Get send queue*/
2459         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2460         if (!TNY_IS_SEND_QUEUE(send_queue)) {
2461                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2462                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2463                              "modest: could not find send queue for account\n");
2464         } else {
2465                 /* Cancel the current send */
2466                 tny_account_cancel (TNY_ACCOUNT (transport_account));
2467
2468                 /* Suspend all pending messages */
2469                 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2470         }
2471
2472  frees:
2473         if (transport_account != NULL)
2474                 g_object_unref (G_OBJECT (transport_account));
2475 }
2476
2477 static void
2478 modest_ui_actions_cancel_send_all (ModestWindow *win)
2479 {
2480         GSList *account_names, *iter;
2481
2482         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2483                                                           TRUE);
2484
2485         iter = account_names;
2486         while (iter) {
2487                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2488                 iter = g_slist_next (iter);
2489         }
2490
2491         modest_account_mgr_free_account_names (account_names);
2492         account_names = NULL;
2493 }
2494
2495 void
2496 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
2497
2498 {
2499         /* Check if accounts exist */
2500         gboolean accounts_exist =
2501                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2502
2503         /* If not, allow the user to create an account before trying to send/receive. */
2504         if (!accounts_exist)
2505                 modest_ui_actions_on_accounts (NULL, win);
2506
2507         /* Cancel all sending operaitons */
2508         modest_ui_actions_cancel_send_all (win);
2509 }
2510
2511 /*
2512  * Refreshes all accounts. This function will be used by automatic
2513  * updates
2514  */
2515 void
2516 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2517                                        gboolean force_connection,
2518                                        gboolean poke_status,
2519                                        gboolean interactive)
2520 {
2521         GSList *account_names, *iter;
2522
2523         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2524                                                           TRUE);
2525
2526         iter = account_names;
2527         while (iter) {
2528                 modest_ui_actions_do_send_receive ((const char*) iter->data,
2529                                                    force_connection,
2530                                                    poke_status, interactive, win);
2531                 iter = g_slist_next (iter);
2532         }
2533
2534         modest_account_mgr_free_account_names (account_names);
2535         account_names = NULL;
2536 }
2537
2538 /*
2539  * Handler of the click on Send&Receive button in the main toolbar
2540  */
2541 void
2542 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2543 {
2544         /* Check if accounts exist */
2545         gboolean accounts_exist;
2546
2547         accounts_exist =
2548                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2549
2550         /* If not, allow the user to create an account before trying to send/receive. */
2551         if (!accounts_exist)
2552                 modest_ui_actions_on_accounts (NULL, win);
2553
2554         /* Refresh the current folder. The if is always TRUE it's just an extra check */
2555 #ifndef MODEST_TOOLKIT_HILDON2
2556         if (MODEST_IS_MAIN_WINDOW (win)) {
2557                 GtkWidget *folder_view;
2558                 TnyFolderStore *folder_store;
2559
2560                 folder_view =
2561                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2562                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2563                 if (!folder_view)
2564                         return;
2565
2566                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2567
2568                 if (folder_store)
2569                         g_object_unref (folder_store);
2570                 /* Refresh the active account. Force the connection if needed
2571                    and poke the status of all folders */
2572                 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2573 #else
2574         if (MODEST_IS_ACCOUNTS_WINDOW (win)) {
2575                 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2576 #endif
2577         } else {
2578                 const gchar *active_account;
2579                 active_account = modest_window_get_active_account (MODEST_WINDOW (win));
2580
2581                 modest_ui_actions_do_send_receive (active_account, TRUE, TRUE, TRUE, win);
2582         }
2583
2584 }
2585
2586 #ifndef MODEST_TOOLKIT_HILDON2
2587 void
2588 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2589 {
2590         ModestConf *conf;
2591         GtkWidget *header_view;
2592
2593         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2594
2595         header_view = modest_main_window_get_child_widget (main_window,
2596                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2597         if (!header_view)
2598                 return;
2599
2600         conf = modest_runtime_get_conf ();
2601
2602         /* what is saved/restored is depending on the style; thus; we save with
2603          * old style, then update the style, and restore for this new style
2604          */
2605         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2606
2607         if (modest_header_view_get_style
2608             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2609                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2610                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
2611         else
2612                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2613                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
2614
2615         modest_widget_memory_restore (conf, G_OBJECT(header_view),
2616                                       MODEST_CONF_HEADER_VIEW_KEY);
2617 }
2618
2619 void
2620 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2621                                       TnyHeader *header,
2622                                       ModestMainWindow *main_window)
2623 {
2624         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2625         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2626
2627         /* in the case the folder is empty, show the empty folder message and focus
2628          * folder view */
2629         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2630                 if (modest_header_view_is_empty (header_view)) {
2631                         TnyFolder *folder = modest_header_view_get_folder (header_view);
2632                         GtkWidget *folder_view =
2633                                 modest_main_window_get_child_widget (main_window,
2634                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2635                         if (folder != NULL) {
2636                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2637                                 g_object_unref (folder);
2638                         }
2639                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2640                         return;
2641                 }
2642         }
2643         /* If no header has been selected then exit */
2644         if (!header)
2645                 return;
2646
2647         /* Update focus */
2648         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2649             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2650
2651         /* Update toolbar dimming state */
2652         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2653         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2654 }
2655 #endif
2656
2657 void
2658 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2659                                        TnyHeader *header,
2660                                        GtkTreePath *path,
2661                                        ModestWindow *window)
2662 {
2663         GtkTreeRowReference *rowref;
2664
2665         g_return_if_fail (MODEST_IS_WINDOW(window));
2666         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2667         g_return_if_fail (TNY_IS_HEADER (header));
2668
2669         if (modest_header_view_count_selected_headers (header_view) > 1) {
2670                 /* Don't allow activation if there are more than one message selected */
2671                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2672                 return;
2673         }
2674
2675         /* we check for low-mem; in that case, show a warning, and don't allow
2676          * activating headers
2677          */
2678         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2679                 return;
2680
2681 #ifndef MODEST_TOOLKIT_HILDON2
2682         GtkWidget *open_widget;
2683         if (MODEST_IS_MAIN_WINDOW (window)) {
2684                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2685                 open_widget = modest_window_get_action_widget (MODEST_WINDOW (window), "/MenuBar/EmailMenu/EmailOpenMenu");
2686                 if (!GTK_WIDGET_IS_SENSITIVE (open_widget))
2687                         return;
2688         }
2689 #endif
2690
2691         rowref = gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)), path);
2692         open_msg_from_header (header, rowref, MODEST_WINDOW (window));
2693         gtk_tree_row_reference_free (rowref);
2694 }
2695
2696 #ifndef MODEST_TOOLKIT_HILDON2
2697 static void
2698 set_active_account_from_tny_account (TnyAccount *account,
2699                                      ModestWindow *window)
2700 {
2701         const gchar *server_acc_name = tny_account_get_id (account);
2702
2703         /* We need the TnyAccount provided by the
2704            account store because that is the one that
2705            knows the name of the Modest account */
2706         TnyAccount *modest_server_account =
2707                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2708                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2709                                                              server_acc_name);
2710         if (!modest_server_account) {
2711                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2712                 return;
2713         }
2714
2715         /* Update active account, but only if it's not a pseudo-account */
2716         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2717             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2718                 const gchar *modest_acc_name =
2719                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2720                 if (modest_acc_name)
2721                         modest_window_set_active_account (window, modest_acc_name);
2722         }
2723
2724         g_object_unref (modest_server_account);
2725 }
2726
2727 static void
2728 folder_refreshed_cb (ModestMailOperation *mail_op,
2729                      TnyFolder *folder,
2730                      gpointer user_data)
2731 {
2732         ModestMainWindow *win = NULL;
2733         GtkWidget *folder_view, *header_view;
2734         const GError *error;
2735
2736         g_return_if_fail (TNY_IS_FOLDER (folder));
2737
2738         win = MODEST_MAIN_WINDOW (user_data);
2739
2740         /* Check if the operation failed due to memory low conditions */
2741         error = modest_mail_operation_get_error (mail_op);
2742         if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
2743             error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
2744                 modest_platform_run_information_dialog (GTK_WINDOW (win),
2745                                                         _KR("memr_ib_operation_disabled"),
2746                                                         TRUE);
2747                 return;
2748         }
2749
2750         folder_view =
2751                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2752         header_view =
2753                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2754
2755         if (folder_view) {
2756                 TnyFolderStore *current_folder;
2757
2758                 current_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2759                 if (current_folder) {
2760                         gboolean different = ((TnyFolderStore *) folder != current_folder);
2761                         g_object_unref (current_folder);
2762                         if (different)
2763                                 return;
2764                 }
2765         }
2766
2767         /* Check if folder is empty and set headers view contents style */
2768         if ((tny_folder_get_all_count (folder) == 0) ||
2769             modest_header_view_is_empty (MODEST_HEADER_VIEW (header_view)))
2770                 modest_main_window_set_contents_style (win,
2771                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2772 }
2773
2774 void
2775 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2776                                                TnyFolderStore *folder_store,
2777                                                gboolean selected,
2778                                                ModestMainWindow *main_window)
2779 {
2780         GtkWidget *header_view;
2781
2782         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2783
2784         header_view = modest_main_window_get_child_widget(main_window,
2785                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2786         if (!header_view)
2787                 return;
2788
2789
2790         if (TNY_IS_ACCOUNT (folder_store)) {
2791                 if (selected) {
2792                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2793
2794                         /* Show account details */
2795                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2796                 }
2797         } else {
2798                 if (TNY_IS_FOLDER (folder_store) && selected) {
2799                         TnyAccount *account;
2800
2801                         /* Update the active account */
2802                         account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2803                         if (account) {
2804                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2805                                 g_object_unref (account);
2806                                 account = NULL;
2807                         }
2808
2809                         /* Set the header style by default, it could
2810                            be changed later by the refresh callback to
2811                            empty */
2812                         modest_main_window_set_contents_style (main_window,
2813                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2814
2815                         /* Set folder on header view. This function
2816                            will call tny_folder_refresh_async so we
2817                            pass a callback that will be called when
2818                            finished. We use that callback to set the
2819                            empty view if there are no messages */
2820                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2821                                                        TNY_FOLDER (folder_store),
2822                                                        TRUE,
2823                                                        MODEST_WINDOW (main_window),
2824                                                        folder_refreshed_cb,
2825                                                        main_window);
2826
2827                         /* Restore configuration. We need to do this
2828                            *after* the set_folder because the widget
2829                            memory asks the header view about its
2830                            folder  */
2831                         modest_widget_memory_restore (modest_runtime_get_conf (),
2832                                                       G_OBJECT(header_view),
2833                                                       MODEST_CONF_HEADER_VIEW_KEY);
2834                 } else {
2835                         /* No need to save the header view
2836                            configuration for Maemo because it only
2837                            saves the sorting stuff and that it's
2838                            already being done by the sort
2839                            dialog. Remove it when the GNOME version
2840                            has the same behaviour */
2841 #ifdef MODEST_TOOLKIT_GTK
2842                         if (modest_main_window_get_contents_style (main_window) ==
2843                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2844                                 modest_widget_memory_save (modest_runtime_get_conf (), 
2845                                                            G_OBJECT (header_view),
2846                                                            MODEST_CONF_HEADER_VIEW_KEY);
2847 #endif
2848                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2849                 }
2850         }
2851
2852         /* Update dimming state */
2853         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2854         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2855 }
2856 #endif
2857
2858 void
2859 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2860                                      ModestWindow *win)
2861 {
2862         GtkWidget *dialog;
2863         gchar *txt, *item;
2864         gboolean online;
2865
2866         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2867
2868         online = tny_device_is_online (modest_runtime_get_device());
2869
2870         if (online) {
2871                 /* already online -- the item is simply not there... */
2872                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2873                                                  GTK_DIALOG_MODAL,
2874                                                  GTK_MESSAGE_WARNING,
2875                                                  GTK_BUTTONS_NONE,
2876                                                  _("The %s you selected cannot be found"),
2877                                                  item);
2878                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2879                 gtk_dialog_run (GTK_DIALOG(dialog));
2880         } else {
2881                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2882                                                       GTK_WINDOW (win),
2883                                                       GTK_DIALOG_MODAL,
2884                                                       _("mcen_bd_dialog_cancel"),
2885                                                       GTK_RESPONSE_REJECT,
2886                                                       _("mcen_bd_dialog_ok"),
2887                                                       GTK_RESPONSE_ACCEPT,
2888                                                       NULL);
2889                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2890                                          "Do you want to get online?"), item);
2891                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2892                                     gtk_label_new (txt), FALSE, FALSE, 0);
2893                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2894                 g_free (txt);
2895
2896                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2897                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2898                         /* TODO: Comment about why is this commented out: */
2899                         /* modest_platform_connect_and_wait (); */
2900                 }
2901         }
2902         gtk_widget_destroy (dialog);
2903 }
2904
2905 void
2906 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2907                                      ModestWindow *win)
2908 {
2909         /* g_debug ("%s %s", __FUNCTION__, link); */
2910 }
2911
2912
2913 void
2914 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2915                                         ModestWindow *win)
2916 {
2917         modest_platform_activate_uri (link);
2918 }
2919
2920 void
2921 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2922                                           ModestWindow *win)
2923 {
2924         modest_platform_show_uri_popup (link);
2925 }
2926
2927 void
2928 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2929                                              ModestWindow *win)
2930 {
2931         /* we check for low-mem; in that case, show a warning, and don't allow
2932          * viewing attachments
2933          */
2934         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2935                 return;
2936
2937         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2938 }
2939
2940 void
2941 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2942                                           const gchar *address,
2943                                           ModestWindow *win)
2944 {
2945         /* g_debug ("%s %s", __FUNCTION__, address); */
2946 }
2947
2948 static void
2949 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2950                       TnyMsg *saved_draft,
2951                       gpointer user_data)
2952 {
2953         ModestMsgEditWindow *edit_window;
2954
2955         /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
2956 #ifndef MODEST_TOOLKIT_HILDON2
2957         ModestMainWindow *win;
2958
2959         /* FIXME. Make the header view sensitive again. This is a
2960          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2961          * for details */
2962         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2963                                          modest_runtime_get_window_mgr(), FALSE));
2964         if (win != NULL) {
2965                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2966                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2967                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2968         }
2969 #endif
2970
2971         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2972
2973         /* Set draft is there was no error */
2974         if (!modest_mail_operation_get_error (mail_op))
2975                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2976
2977         g_object_unref(edit_window);
2978 }
2979
2980 static gboolean
2981 enough_space_for_message (ModestMsgEditWindow *edit_window,
2982                           MsgData *data)
2983 {
2984         guint64 available_disk, expected_size;
2985         gint parts_count;
2986         guint64 parts_size;
2987
2988         /* Check size */
2989         available_disk = modest_utils_get_available_space (NULL);
2990         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2991         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2992                                                       data->html_body,
2993                                                       parts_count,
2994                                                       parts_size);
2995
2996         /* Double check: disk full condition or message too big */
2997         if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
2998             expected_size > available_disk) {
2999                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3000                 modest_platform_information_banner (NULL, NULL, msg);
3001                 g_free (msg);
3002
3003                 return FALSE;
3004         }
3005
3006         /*
3007          * djcb: if we're in low-memory state, we only allow for
3008          * saving messages smaller than
3009          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
3010          * should still allow for sending anything critical...
3011          */
3012         if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
3013             modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
3014                 return FALSE;
3015
3016         /*
3017          * djcb: we also make sure that the attachments are smaller than the max size
3018          * this is for the case where we'd try to forward a message with attachments
3019          * bigger than our max allowed size, or sending an message from drafts which
3020          * somehow got past our checks when attaching.
3021          */
3022         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
3023                 modest_platform_run_information_dialog (
3024                         GTK_WINDOW(edit_window),
3025                         _("mail_ib_error_attachment_size"),
3026                         TRUE);
3027                 return FALSE;
3028         }
3029
3030         return TRUE;
3031 }
3032
3033 gboolean
3034 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3035 {
3036         TnyTransportAccount *transport_account;
3037         ModestMailOperation *mail_operation;
3038         MsgData *data;
3039         gchar *account_name;
3040         ModestAccountMgr *account_mgr;
3041         gboolean had_error = FALSE;
3042
3043         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
3044
3045         data = modest_msg_edit_window_get_msg_data (edit_window);
3046
3047         /* Check size */
3048         if (!enough_space_for_message (edit_window, data)) {
3049                 modest_msg_edit_window_free_msg_data (edit_window, data);
3050                 return FALSE;
3051         }
3052
3053         account_name = g_strdup (data->account_name);
3054         account_mgr = modest_runtime_get_account_mgr();
3055         if (!account_name)
3056                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3057         if (!account_name)
3058                 account_name = modest_account_mgr_get_default_account (account_mgr);
3059         if (!account_name) {
3060                 g_printerr ("modest: no account found\n");
3061                 modest_msg_edit_window_free_msg_data (edit_window, data);
3062                 return FALSE;
3063         }
3064
3065         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
3066                 account_name = g_strdup (data->account_name);
3067         }
3068
3069         transport_account =
3070                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3071                                       (modest_runtime_get_account_store (),
3072                                        account_name,
3073                                        TNY_ACCOUNT_TYPE_TRANSPORT));
3074         if (!transport_account) {
3075                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
3076                 g_free (account_name);
3077                 modest_msg_edit_window_free_msg_data (edit_window, data);
3078                 return FALSE;
3079         }
3080
3081         /* Create the mail operation */
3082         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
3083                                                                         NULL, NULL);
3084         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3085
3086         modest_mail_operation_save_to_drafts (mail_operation,
3087                                               transport_account,
3088                                               data->draft_msg,
3089                                               data->from,
3090                                               data->to, 
3091                                               data->cc, 
3092                                               data->bcc,
3093                                               data->subject,
3094                                               data->plain_body,
3095                                               data->html_body,
3096                                               data->attachments,
3097                                               data->images,
3098                                               data->priority_flags,
3099                                               data->references,
3100                                               data->in_reply_to,
3101                                               on_save_to_drafts_cb,
3102                                               g_object_ref(edit_window));
3103
3104 #ifdef MODEST_TOOLKIT_HILDON2
3105         /* In hildon2 we always show the information banner on saving to drafts.
3106          * It will be a system information banner in this case.
3107          */
3108         gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3109         modest_platform_information_banner (NULL, NULL, text);
3110         g_free (text);
3111 #else
3112         ModestMainWindow *win = NULL;
3113
3114         /* Use the main window as the parent of the banner, if the
3115            main window does not exist it won't be shown, if the parent
3116            window exists then it's properly shown. We don't use the
3117            editor window because it could be closed (save to drafts
3118            could happen after closing the window */
3119         win = (ModestMainWindow *)
3120                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
3121         if (win) {
3122                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3123                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
3124                 g_free (text);
3125         }
3126 #endif
3127         modest_msg_edit_window_set_modified (edit_window, FALSE);
3128
3129         /* Frees */
3130         g_free (account_name);
3131         g_object_unref (G_OBJECT (transport_account));
3132         g_object_unref (G_OBJECT (mail_operation));
3133
3134         modest_msg_edit_window_free_msg_data (edit_window, data);
3135
3136 #ifndef MODEST_TOOLKIT_HILDON2
3137         /* ** FIXME **
3138          * If the drafts folder is selected then make the header view
3139          * insensitive while the message is being saved to drafts
3140          * (it'll be sensitive again in on_save_to_drafts_cb()). This
3141          * is not very clean but it avoids letting the drafts folder
3142          * in an inconsistent state: the user could edit the message
3143          * being saved and undesirable things would happen.
3144          * In the average case the user won't notice anything at
3145          * all. In the worst case (the user is editing a really big
3146          * file from Drafts) the header view will be insensitive
3147          * during the saving process (10 or 20 seconds, depending on
3148          * the message). Anyway this is just a quick workaround: once
3149          * we find a better solution it should be removed
3150          * See NB#65125 (commend #18) for details.
3151          */
3152         if (!had_error && win != NULL) {
3153                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
3154                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
3155                 if (view != NULL) {
3156                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
3157                         if (folder) {
3158                                 if (modest_tny_folder_is_local_folder(folder)) {
3159                                         TnyFolderType folder_type;
3160                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
3161                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
3162                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
3163                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3164                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
3165                                         }
3166                                 }
3167                         }
3168                         if (folder != NULL) g_object_unref(folder);
3169                 }
3170         }
3171 #endif
3172
3173         return !had_error;
3174 }
3175
3176 /* For instance, when clicking the Send toolbar button when editing a message: */
3177 gboolean
3178 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3179 {
3180         TnyTransportAccount *transport_account = NULL;
3181         gboolean had_error = FALSE;
3182         MsgData *data;
3183         ModestAccountMgr *account_mgr;
3184         gchar *account_name;
3185         ModestMailOperation *mail_operation;
3186         gchar *recipients;
3187
3188         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3189
3190         /* Check names but do not automatically add them to addressbook */
3191         if (!modest_msg_edit_window_check_names (edit_window, FALSE))
3192                 return TRUE;
3193
3194         data = modest_msg_edit_window_get_msg_data (edit_window);
3195
3196         recipients = g_strconcat (data->to?data->to:"", 
3197                                   data->cc?data->cc:"",
3198                                   data->bcc?data->bcc:"",
3199                                   NULL);
3200         if (recipients == NULL || recipients[0] == '\0') {
3201                 /* Empty subject -> no send */
3202                 g_free (recipients);
3203                 modest_msg_edit_window_free_msg_data (edit_window, data);
3204                 return FALSE;
3205         }
3206         g_free (recipients);
3207
3208         /* Check size */
3209         if (!enough_space_for_message (edit_window, data)) {
3210                 modest_msg_edit_window_free_msg_data (edit_window, data);
3211                 return FALSE;
3212         }
3213
3214         account_mgr = modest_runtime_get_account_mgr();
3215         account_name = g_strdup (data->account_name);
3216         if (!account_name)
3217                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3218
3219         if (!account_name)
3220                 account_name = modest_account_mgr_get_default_account (account_mgr);
3221
3222         if (!account_name) {
3223                 modest_msg_edit_window_free_msg_data (edit_window, data);
3224                 /* Run account setup wizard */
3225                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3226                         return TRUE;
3227                 }
3228         }
3229
3230         /* Get the currently-active transport account for this modest account: */
3231         if (account_name && strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3232                 transport_account =
3233                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3234                                               (modest_runtime_get_account_store (),
3235                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3236         }
3237
3238         if (!transport_account) {
3239                 modest_msg_edit_window_free_msg_data (edit_window, data);
3240                 /* Run account setup wizard */
3241                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3242                         return TRUE;
3243         }
3244
3245
3246         /* Create the mail operation */
3247         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3248         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3249
3250         modest_mail_operation_send_new_mail (mail_operation,
3251                                              transport_account,
3252                                              data->draft_msg,
3253                                              data->from,
3254                                              data->to,
3255                                              data->cc,
3256                                              data->bcc,
3257                                              data->subject,
3258                                              data->plain_body,
3259                                              data->html_body,
3260                                              data->attachments,
3261                                              data->images,
3262                                              data->references,
3263                                              data->in_reply_to,
3264                                              data->priority_flags);
3265
3266         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3267                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3268
3269         if (modest_mail_operation_get_error (mail_operation) != NULL) {
3270                 const GError *error = modest_mail_operation_get_error (mail_operation);
3271                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3272                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3273                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3274                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3275                         had_error = TRUE;
3276                 }
3277         }
3278
3279         /* Free data: */
3280         g_free (account_name);
3281         g_object_unref (G_OBJECT (transport_account));
3282         g_object_unref (G_OBJECT (mail_operation));
3283
3284         modest_msg_edit_window_free_msg_data (edit_window, data);
3285
3286         if (!had_error) {
3287                 modest_msg_edit_window_set_sent (edit_window, TRUE);
3288
3289                 /* Save settings and close the window: */
3290                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3291         }
3292
3293         return !had_error;
3294 }
3295
3296 void
3297 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3298                                   ModestMsgEditWindow *window)
3299 {
3300         ModestMsgEditFormatState *format_state = NULL;
3301
3302         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3303         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3304
3305         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3306                 return;
3307
3308         format_state = modest_msg_edit_window_get_format_state (window);
3309         g_return_if_fail (format_state != NULL);
3310
3311         format_state->bold = gtk_toggle_action_get_active (action);
3312         modest_msg_edit_window_set_format_state (window, format_state);
3313         g_free (format_state);
3314
3315 }
3316
3317 void
3318 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3319                                      ModestMsgEditWindow *window)
3320 {
3321         ModestMsgEditFormatState *format_state = NULL;
3322
3323         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3324         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3325
3326         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3327                 return;
3328
3329         format_state = modest_msg_edit_window_get_format_state (window);
3330         g_return_if_fail (format_state != NULL);
3331
3332         format_state->italics = gtk_toggle_action_get_active (action);
3333         modest_msg_edit_window_set_format_state (window, format_state);
3334         g_free (format_state);
3335
3336 }
3337
3338 void
3339 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3340                                      ModestMsgEditWindow *window)
3341 {
3342         ModestMsgEditFormatState *format_state = NULL;
3343
3344         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3345         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3346
3347         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3348                 return;
3349
3350         format_state = modest_msg_edit_window_get_format_state (window);
3351         g_return_if_fail (format_state != NULL);
3352
3353         format_state->bullet = gtk_toggle_action_get_active (action);
3354         modest_msg_edit_window_set_format_state (window, format_state);
3355         g_free (format_state);
3356
3357 }
3358
3359 void
3360 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3361                                      GtkRadioAction *selected,
3362                                      ModestMsgEditWindow *window)
3363 {
3364         ModestMsgEditFormatState *format_state = NULL;
3365         GtkJustification value;
3366
3367         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3368
3369         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3370                 return;
3371
3372         value = gtk_radio_action_get_current_value (selected);
3373
3374         format_state = modest_msg_edit_window_get_format_state (window);
3375         g_return_if_fail (format_state != NULL);
3376
3377         format_state->justification = value;
3378         modest_msg_edit_window_set_format_state (window, format_state);
3379         g_free (format_state);
3380 }
3381
3382 void
3383 modest_ui_actions_on_select_editor_color (GtkAction *action,
3384                                           ModestMsgEditWindow *window)
3385 {
3386         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3387         g_return_if_fail (GTK_IS_ACTION (action));
3388
3389         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3390                 return;
3391
3392         modest_msg_edit_window_select_color (window);
3393 }
3394
3395 void
3396 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3397                                                      ModestMsgEditWindow *window)
3398 {
3399         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3400         g_return_if_fail (GTK_IS_ACTION (action));
3401
3402         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3403                 return;
3404
3405         modest_msg_edit_window_select_background_color (window);
3406 }
3407
3408 void
3409 modest_ui_actions_on_insert_image (GObject *object,
3410                                    ModestMsgEditWindow *window)
3411 {
3412         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3413
3414
3415         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3416                 return;
3417
3418         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3419                 return;
3420
3421         modest_msg_edit_window_insert_image (window);
3422 }
3423
3424 void
3425 modest_ui_actions_on_attach_file (GtkAction *action,
3426                                   ModestMsgEditWindow *window)
3427 {
3428         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3429         g_return_if_fail (GTK_IS_ACTION (action));
3430
3431         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3432                 return;
3433
3434         modest_msg_edit_window_offer_attach_file (window);
3435 }
3436
3437 void
3438 modest_ui_actions_on_remove_attachments (GtkAction *action,
3439                                          ModestMsgEditWindow *window)
3440 {
3441         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3442
3443         modest_msg_edit_window_remove_attachments (window, NULL);
3444 }
3445
3446 static void
3447 do_create_folder_cb (ModestMailOperation *mail_op,
3448                      TnyFolderStore *parent_folder,
3449                      TnyFolder *new_folder,
3450                      gpointer user_data)
3451 {
3452         gchar *suggested_name = (gchar *) user_data;
3453         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3454         const GError *error;
3455
3456         error = modest_mail_operation_get_error (mail_op);
3457         if (error) {
3458                 gboolean disk_full = FALSE;
3459                 TnyAccount *account;
3460                 /* Show an error. If there was some problem writing to
3461                    disk, show it, otherwise show the generic folder
3462                    create error. We do it here and not in an error
3463                    handler because the call to do_create_folder will
3464                    stop the main loop in a gtk_dialog_run and then,
3465                    the message won't be shown until that dialog is
3466                    closed */
3467                 account = modest_mail_operation_get_account (mail_op);
3468                 if (account) {
3469                         disk_full =
3470                                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3471                                                                                 (GtkWidget *) source_win,
3472                                                                                 (GError *) error,
3473                                                                                 account,
3474                                                                                 _("mail_in_ui_folder_create_error_memory"));
3475                         g_object_unref (account);
3476                 }
3477                 if (!disk_full) {
3478                         /* Show an error and try again if there is no
3479                            full memory condition */
3480                         modest_platform_information_banner ((GtkWidget *) source_win, NULL,
3481                                                             _("mail_in_ui_folder_create_error"));
3482                         do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3483                 }
3484
3485         } else {
3486                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3487                  * FIXME: any other? */
3488                 GtkWidget *folder_view;
3489
3490 #ifndef MODEST_TOOLKIT_HILDON2
3491                 if (MODEST_IS_MAIN_WINDOW(source_win))
3492                         folder_view =
3493                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3494                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3495                 else
3496 #endif
3497                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3498                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3499
3500                 /* Select the newly created folder. It could happen
3501                    that the widget is no longer there (i.e. the window
3502                    has been destroyed, so we need to check this */
3503                 if (folder_view)
3504                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3505                                                           new_folder, FALSE);
3506                 g_object_unref (new_folder);
3507         }
3508         /* Free. Note that the first time it'll be NULL so noop */
3509         g_free (suggested_name);
3510         g_object_unref (source_win);
3511 }
3512
3513 typedef struct {
3514         gchar *folder_name;
3515         TnyFolderStore *parent;
3516 } CreateFolderConnect;
3517
3518 static void
3519 do_create_folder_performer (gboolean canceled,
3520                          GError *err,
3521                          GtkWindow *parent_window,
3522                          TnyAccount *account,
3523                          gpointer user_data)
3524 {
3525         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
3526         ModestMailOperation *mail_op;
3527
3528         if (canceled || err) {
3529                 /* In disk full conditions we could get this error here */
3530                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3531                                                                 (GtkWidget *) parent_window, err,
3532                                                                 NULL, _("mail_in_ui_folder_create_error_memory"));
3533
3534                 /* This happens if we have selected the outbox folder
3535                    as the parent */
3536                 if (err && err->code == TNY_SERVICE_ERROR_UNKNOWN &&
3537                     TNY_IS_MERGE_FOLDER (helper->parent)) {
3538                         /* Show an error and retry */
3539                         modest_platform_information_banner ((GtkWidget *) parent_window,
3540                                                             NULL,
3541                                                             _("mail_in_ui_folder_create_error"));
3542
3543                         do_create_folder (parent_window, helper->parent, helper->folder_name);
3544                 }
3545
3546                 goto frees;
3547         }
3548
3549         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3550         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3551                                          mail_op);
3552         modest_mail_operation_create_folder (mail_op,
3553                                              helper->parent,
3554                                              (const gchar *) helper->folder_name,
3555                                              do_create_folder_cb,
3556                                              g_strdup (helper->folder_name));
3557         g_object_unref (mail_op);
3558
3559  frees:
3560         if (helper->parent)
3561                 g_object_unref (helper->parent);
3562         if (helper->folder_name)
3563                 g_free (helper->folder_name);
3564         g_slice_free (CreateFolderConnect, helper);
3565 }
3566
3567
3568 static void
3569 do_create_folder (GtkWindow *parent_window,
3570                   TnyFolderStore *suggested_parent,
3571                   const gchar *suggested_name)
3572 {
3573         gint result;
3574         gchar *folder_name = NULL;
3575         TnyFolderStore *parent_folder = NULL;
3576
3577         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3578                                                         suggested_parent,
3579                                                         (gchar *) suggested_name,
3580                                                         &folder_name,
3581                                                         &parent_folder);
3582
3583         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3584                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3585                 helper->folder_name = g_strdup (folder_name);
3586                 helper->parent = g_object_ref (parent_folder);
3587
3588                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3589                                                                TRUE,
3590                                                                parent_folder,
3591                                                                do_create_folder_performer,
3592                                                                helper);
3593         }
3594
3595         if (folder_name)
3596                 g_free (folder_name);
3597         if (parent_folder)
3598                 g_object_unref (parent_folder);
3599 }
3600
3601 static void
3602 modest_ui_actions_create_folder(GtkWidget *parent_window,
3603                                 GtkWidget *folder_view,
3604                                 TnyFolderStore *parent_folder)
3605 {
3606         if (!parent_folder) {
3607 #ifdef MODEST_TOOLKIT_HILDON2
3608                 ModestTnyAccountStore *acc_store;
3609
3610                 acc_store = modest_runtime_get_account_store ();
3611
3612                 parent_folder = (TnyFolderStore *)
3613                         modest_tny_account_store_get_local_folders_account (acc_store);
3614 #else
3615                 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3616 #endif
3617         }
3618
3619         if (parent_folder) {
3620                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3621                 g_object_unref (parent_folder);
3622         }
3623 }
3624
3625 void
3626 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3627 {
3628
3629         g_return_if_fail (MODEST_IS_WINDOW(window));
3630
3631 #ifndef MODEST_TOOLKIT_HILDON2
3632         if (MODEST_IS_MAIN_WINDOW (window)) {
3633                 GtkWidget *folder_view;
3634
3635                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3636                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3637                 if (!folder_view)
3638                         return;
3639
3640                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3641 #else
3642         if (MODEST_IS_FOLDER_WINDOW (window)) {
3643                 GtkWidget *folder_view;
3644
3645                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3646                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3647 #endif
3648         } else {
3649                 g_assert_not_reached ();
3650         }
3651 }
3652
3653 static void
3654 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3655                                                gpointer user_data)
3656 {
3657         const GError *error = NULL;
3658         gchar *message = NULL;
3659         gboolean mem_full;
3660         TnyAccount *account = modest_mail_operation_get_account (mail_op);
3661
3662         /* Get error message */
3663         error = modest_mail_operation_get_error (mail_op);
3664         if (!error)
3665                 g_return_if_reached ();
3666
3667         mem_full = modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
3668                                                                 (GError *) error, account);
3669         if (mem_full) {
3670                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3671         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3672                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3673                 message = _CS("ckdg_ib_folder_already_exists");
3674         } else if (error->domain == TNY_ERROR_DOMAIN &&
3675                    error->code == TNY_SERVICE_ERROR_STATE) {
3676                 /* This means that the folder is already in use (a
3677                    message is opened for example */
3678                 message = _("emev_ni_internal_error");
3679         } else {
3680                 message = _CS("ckdg_ib_unable_to_rename");
3681         }
3682
3683         /* We don't set a parent for the dialog because the dialog
3684            will be destroyed so the banner won't appear */
3685         modest_platform_information_banner (NULL, NULL, message);
3686
3687         if (account)
3688                 g_object_unref (account);
3689         if (mem_full)
3690                 g_free (message);
3691 }
3692
3693 typedef struct {
3694         TnyFolderStore *folder;
3695         gchar *new_name;
3696 } RenameFolderInfo;
3697
3698 static void
3699 on_rename_folder_cb (ModestMailOperation *mail_op,
3700                      TnyFolder *new_folder,
3701                      gpointer user_data)
3702 {
3703         ModestFolderView *folder_view;
3704
3705         /* If the window was closed when renaming a folder, or if
3706          * it's not a main window this will happen */
3707         if (!MODEST_IS_FOLDER_VIEW (user_data))
3708                 return;
3709
3710         folder_view = MODEST_FOLDER_VIEW (user_data);
3711         /* Note that if the rename fails new_folder will be NULL */
3712         if (new_folder) {
3713                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3714 #ifndef MODEST_TOOLKIT_HILDON2
3715         } else {
3716                 modest_folder_view_select_first_inbox_or_local (folder_view);
3717 #endif
3718         }
3719         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3720 }
3721
3722 static void
3723 on_rename_folder_performer (gboolean canceled,
3724                             GError *err,
3725                             GtkWindow *parent_window,
3726                             TnyAccount *account,
3727                             gpointer user_data)
3728 {
3729         ModestMailOperation *mail_op = NULL;
3730         GtkTreeSelection *sel = NULL;
3731         GtkWidget *folder_view = NULL;
3732         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3733
3734         if (canceled || err) {
3735                 /* In disk full conditions we could get this error here */
3736                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3737                                                                 (GtkWidget *) parent_window, err,
3738                                                                 account, NULL);
3739         } else {
3740
3741                 mail_op =
3742                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3743                                         modest_ui_actions_rename_folder_error_handler,
3744                                         parent_window, NULL);
3745
3746                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3747                                 mail_op);
3748 #ifndef MODEST_TOOLKIT_HILDON2
3749                 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3750
3751                         folder_view = modest_main_window_get_child_widget (
3752                                 MODEST_MAIN_WINDOW (parent_window),
3753                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3754                 }
3755 #else
3756                 if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3757                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3758                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3759                 }
3760 #endif
3761
3762                 /* Clear the folders view */
3763                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3764                 gtk_tree_selection_unselect_all (sel);
3765
3766                 /* Actually rename the folder */
3767                 modest_mail_operation_rename_folder (mail_op,
3768                                                      TNY_FOLDER (data->folder),
3769                                                      (const gchar *) (data->new_name),
3770                                                      on_rename_folder_cb,
3771                                                      folder_view);
3772                 g_object_unref (mail_op);
3773         }
3774
3775         g_object_unref (data->folder);
3776         g_free (data->new_name);
3777         g_free (data);
3778 }
3779
3780 void
3781 modest_ui_actions_on_rename_folder (GtkAction *action,
3782                                      ModestWindow *window)
3783 {
3784         modest_ui_actions_on_edit_mode_rename_folder (window);
3785 }
3786
3787 gboolean
3788 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3789 {
3790         TnyFolderStore *folder;
3791         GtkWidget *folder_view;
3792         gboolean do_rename = TRUE;
3793
3794         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3795
3796 #ifndef MODEST_TOOLKIT_HILDON2
3797         if (MODEST_IS_MAIN_WINDOW (window)) {
3798                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3799                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3800                 if (!folder_view)
3801                         return FALSE;
3802 #else
3803         if (MODEST_IS_FOLDER_WINDOW (window)) {
3804                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3805 #endif
3806         } else {
3807                 return FALSE;
3808         }
3809
3810         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3811
3812         if (!folder)
3813                 return FALSE;
3814
3815         if (TNY_IS_FOLDER (folder)) {
3816                 gchar *folder_name = NULL;
3817                 gint response;
3818                 const gchar *current_name;
3819                 TnyFolderStore *parent;
3820
3821                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3822                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3823                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3824                                                                      parent, current_name,
3825                                                                      &folder_name);
3826                 g_object_unref (parent);
3827
3828                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3829                         do_rename = FALSE;
3830                 } else {
3831                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3832                         rename_folder_data->folder = g_object_ref (folder);
3833                         rename_folder_data->new_name = folder_name;
3834                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3835                                         folder, on_rename_folder_performer, rename_folder_data);
3836                 }
3837         }
3838         g_object_unref (folder);
3839         return do_rename;
3840 }
3841
3842 static void
3843 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3844                                                gpointer user_data)
3845 {
3846         GObject *win = modest_mail_operation_get_source (mail_op);
3847
3848         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3849                                                 _("mail_in_ui_folder_delete_error"),
3850                                                 FALSE);
3851         g_object_unref (win);
3852 }
3853
3854 typedef struct {
3855         TnyFolderStore *folder;
3856         gboolean move_to_trash;
3857 } DeleteFolderInfo;
3858
3859 static void
3860 on_delete_folder_cb (gboolean canceled,
3861                   GError *err,
3862                   GtkWindow *parent_window,
3863                   TnyAccount *account,
3864                   gpointer user_data)
3865 {
3866         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3867         GtkWidget *folder_view;
3868         ModestMailOperation *mail_op;
3869         GtkTreeSelection *sel;
3870
3871         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
3872                 /* Note that the connection process can fail due to
3873                    memory low conditions as it can not successfully
3874                    store the summary */
3875                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3876                                                                      (GtkWidget*) parent_window, err,
3877                                                                      account, NULL))
3878                         g_debug ("Error connecting when trying to delete a folder");
3879                 g_object_unref (G_OBJECT (info->folder));
3880                 g_free (info);
3881                 return;
3882         }
3883
3884 #ifndef MODEST_TOOLKIT_HILDON2
3885         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
3886                 folder_view = modest_main_window_get_child_widget (
3887                         MODEST_MAIN_WINDOW (parent_window),
3888                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3889 #else
3890         if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3891                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
3892 #endif
3893         } else {
3894                 g_object_unref (G_OBJECT (info->folder));
3895                 g_free (info);
3896                 return;
3897         }
3898
3899         /* Unselect the folder before deleting it to free the headers */
3900         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3901         gtk_tree_selection_unselect_all (sel);
3902
3903         /* Create the mail operation */
3904         mail_op =
3905                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3906                                 modest_ui_actions_delete_folder_error_handler,
3907                                 NULL, NULL);
3908
3909         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3910                         mail_op);
3911         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3912
3913 #ifndef MODEST_TOOLKIT_HILDON2
3914         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3915 #endif
3916
3917         g_object_unref (mail_op);
3918         g_object_unref (info->folder);
3919         g_free (info);
3920 }
3921
3922 static gboolean
3923 delete_folder (ModestWindow *window, gboolean move_to_trash)
3924 {
3925         TnyFolderStore *folder;
3926         GtkWidget *folder_view;
3927         gint response;
3928         gchar *message;
3929
3930         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3931
3932 #ifndef MODEST_TOOLKIT_HILDON2
3933         if (MODEST_IS_MAIN_WINDOW (window)) {
3934
3935                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3936                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3937 #else
3938         if (MODEST_IS_FOLDER_WINDOW (window)) {
3939                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3940 #endif
3941         } else {
3942                 return FALSE;
3943         }
3944         if (!folder_view)
3945                 return FALSE;
3946
3947         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3948
3949         if (!folder)
3950                 return FALSE;
3951
3952         /* Show an error if it's an account */
3953         if (!TNY_IS_FOLDER (folder)) {
3954                 modest_platform_run_information_dialog (GTK_WINDOW (window),
3955                                                         _("mail_in_ui_folder_delete_error"),
3956                                                         FALSE);
3957                 g_object_unref (G_OBJECT (folder));
3958                 return FALSE;
3959         }
3960
3961         /* Ask the user */
3962         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
3963                                     tny_folder_get_name (TNY_FOLDER (folder)));
3964         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
3965                                                             (const gchar *) message);
3966         g_free (message);
3967
3968         if (response == GTK_RESPONSE_OK) {
3969                 TnyAccount *account = NULL;
3970                 DeleteFolderInfo *info = NULL;
3971                 info = g_new0(DeleteFolderInfo, 1);
3972                 info->folder = g_object_ref (folder);
3973                 info->move_to_trash = move_to_trash;
3974
3975                 account = tny_folder_get_account (TNY_FOLDER (folder));
3976                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
3977                                                                TRUE,
3978                                                                TNY_FOLDER_STORE (account),
3979                                                                on_delete_folder_cb, info);
3980                 g_object_unref (account);
3981                 g_object_unref (folder);
3982                 return TRUE;
3983         } else {
3984                 return FALSE;
3985         }
3986 }
3987
3988 void
3989 modest_ui_actions_on_delete_folder (GtkAction *action,
3990                                     ModestWindow *window)
3991 {
3992         modest_ui_actions_on_edit_mode_delete_folder (window);
3993 }
3994
3995 gboolean
3996 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
3997 {
3998         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
3999
4000         return delete_folder (window, FALSE);
4001 }
4002
4003 #ifndef MODEST_TOOLKIT_HILDON2
4004 void
4005 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
4006 {
4007         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4008
4009         delete_folder (MODEST_WINDOW (main_window), TRUE);
4010 }
4011 #endif
4012
4013 typedef struct _PasswordDialogFields {
4014         GtkWidget *username;
4015         GtkWidget *password;
4016         GtkWidget *dialog;
4017 } PasswordDialogFields;
4018
4019 static void
4020 password_dialog_check_field (GtkEditable *editable,
4021                              PasswordDialogFields *fields)
4022 {
4023         const gchar *value;
4024         gboolean any_value_empty = FALSE;
4025
4026         value = modest_entry_get_text (fields->username);
4027         if ((value == NULL) || value[0] == '\0') {
4028                 any_value_empty = TRUE;
4029         }
4030         value = modest_entry_get_text (fields->password);
4031         if ((value == NULL) || value[0] == '\0') {
4032                 any_value_empty = TRUE;
4033         }
4034         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
4035 }
4036
4037 void
4038 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
4039                                          const gchar* server_account_name,
4040                                          gchar **username,
4041                                          gchar **password,
4042                                          gboolean *cancel,
4043                                          gboolean *remember,
4044                                          ModestMainWindow *main_window)
4045 {
4046         g_return_if_fail(server_account_name);
4047         gboolean completed = FALSE;
4048         PasswordDialogFields *fields = NULL;
4049
4050         /* Initalize output parameters: */
4051         if (cancel)
4052                 *cancel = FALSE;
4053
4054         if (remember)
4055                 *remember = TRUE;
4056
4057 #ifndef MODEST_TOOLKIT_GTK
4058         /* Maemo uses a different (awkward) button order,
4059          * It should probably just use gtk_alternative_dialog_button_order ().
4060          */
4061 #ifdef MODEST_TOOLKIT_HILDON2
4062         GtkWidget *dialog =
4063                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4064                                              NULL,
4065                                              GTK_DIALOG_MODAL,
4066                                              _HL("wdgt_bd_done"),
4067                                              GTK_RESPONSE_ACCEPT,
4068                                              NULL);
4069         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
4070                                         HILDON_MARGIN_DOUBLE);
4071 #else
4072         GtkWidget *dialog =
4073                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4074                                              NULL,
4075                                              GTK_DIALOG_MODAL,
4076                                              _("mcen_bd_dialog_ok"),
4077                                              GTK_RESPONSE_ACCEPT,
4078                                              _("mcen_bd_dialog_cancel"),
4079                                              GTK_RESPONSE_REJECT,
4080                                              NULL);
4081 #endif /* MODEST_TOOLKIT_HILDON2 */
4082 #else
4083         GtkWidget *dialog =
4084                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4085                                              NULL,
4086                                              GTK_DIALOG_MODAL,
4087                                              GTK_STOCK_CANCEL,
4088                                              GTK_RESPONSE_REJECT,
4089                                              GTK_STOCK_OK,
4090                                              GTK_RESPONSE_ACCEPT,
4091                                              NULL);
4092 #endif /* MODEST_TOOLKIT_GTK */
4093
4094         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
4095
4096         gchar *server_name = modest_account_mgr_get_server_account_hostname (
4097                 modest_runtime_get_account_mgr(), server_account_name);
4098         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
4099                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
4100                 if (cancel)
4101                         *cancel = TRUE;
4102                 gtk_widget_destroy (dialog);
4103                 return;
4104         }
4105
4106         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
4107         GtkWidget *label = gtk_label_new (txt);
4108         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
4109         g_free (txt);
4110         g_free (server_name);
4111         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
4112                             FALSE, FALSE, 0);
4113         server_name = NULL;
4114
4115         /* username: */
4116         gchar *initial_username = modest_account_mgr_get_server_account_username (
4117                 modest_runtime_get_account_mgr(), server_account_name);
4118
4119         GtkWidget *entry_username = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
4120         if (initial_username)
4121                 modest_entry_set_text (entry_username, initial_username);
4122
4123         /* Dim this if a connection has ever succeeded with this username,
4124          * as per the UI spec: */
4125         /* const gboolean username_known =  */
4126         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
4127         /*              modest_runtime_get_account_mgr(), server_account_name); */
4128         /* gtk_widget_set_sensitive (entry_username, !username_known); */
4129
4130         /* We drop the username sensitive code and disallow changing it here
4131          * as tinymail does not support really changing the username in the callback
4132          */
4133         gtk_widget_set_sensitive (entry_username, FALSE);
4134
4135 #ifndef MODEST_TOOLKIT_GTK
4136         /* Auto-capitalization is the default, so let's turn it off: */
4137         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
4138
4139         /* Create a size group to be used by all captions.
4140          * Note that HildonCaption does not create a default size group if we do not specify one.
4141          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
4142         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
4143
4144 #ifdef MODEST_TOOLKIT_HILDON2
4145         GtkWidget *caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4146                                                                   _("mail_fi_username"), FALSE,
4147                                                                   entry_username);
4148 #else
4149         GtkWidget *caption = hildon_caption_new (sizegroup,
4150                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
4151 #endif
4152         gtk_widget_show (entry_username);
4153         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4154                 FALSE, FALSE, MODEST_MARGIN_HALF);
4155         gtk_widget_show (caption);
4156 #else
4157         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
4158                             TRUE, FALSE, 0);
4159 #endif /* !MODEST_TOOLKIT_GTK */
4160
4161         /* password: */
4162         GtkWidget *entry_password = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
4163         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
4164         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
4165
4166 #ifndef MODEST_TOOLKIT_GTK
4167         /* Auto-capitalization is the default, so let's turn it off: */
4168         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
4169                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
4170
4171         caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4172                                                        _("mail_fi_password"), FALSE,
4173                                                        entry_password);
4174         gtk_widget_show (entry_password);
4175         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4176                 FALSE, FALSE, MODEST_MARGIN_HALF);
4177         gtk_widget_show (caption);
4178         g_object_unref (sizegroup);
4179 #else
4180         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
4181                             TRUE, FALSE, 0);
4182 #endif /* !MODEST_TOOLKIT_GTK */
4183
4184         if (initial_username != NULL)
4185                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
4186
4187 /* This is not in the Maemo UI spec:
4188         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
4189         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
4190                             TRUE, FALSE, 0);
4191 */
4192
4193         fields = g_slice_new0 (PasswordDialogFields);
4194         fields->username = entry_username;
4195         fields->password = entry_password;
4196         fields->dialog = dialog;
4197
4198         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
4199         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
4200         password_dialog_check_field (NULL, fields);
4201
4202         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4203
4204         while (!completed) {
4205
4206                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
4207                         if (username) {
4208                                 *username = g_strdup (modest_entry_get_text (entry_username));
4209
4210                                 /* Note that an empty field becomes the "" string */
4211                                 if (*username && strlen (*username) > 0) {
4212                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
4213                                                                                         server_account_name,
4214                                                                                         *username);
4215                                         completed = TRUE;
4216
4217                                         const gboolean username_was_changed =
4218                                                 (strcmp (*username, initial_username) != 0);
4219                                         if (username_was_changed) {
4220                                                 g_warning ("%s: tinymail does not yet support changing the "
4221                                                            "username in the get_password() callback.\n", __FUNCTION__);
4222                                         }
4223                                 } else {
4224                                         g_free (*username);
4225                                         *username = NULL;
4226                                         /* Show error */
4227                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
4228                                                                             _("mcen_ib_username_pw_incorrect"));
4229                                         completed = FALSE;
4230                                 }
4231                         }
4232
4233                         if (password) {
4234                                 *password = g_strdup (modest_entry_get_text (entry_password));
4235
4236                                 /* We do not save the password in the configuration,
4237                                  * because this function is only called for passwords that should
4238                                  * not be remembered:
4239                                  modest_server_account_set_password (
4240                                  modest_runtime_get_account_mgr(), server_account_name,
4241                                  *password);
4242                                  */
4243                         }
4244                         if (cancel)
4245                                 *cancel   = FALSE;
4246                 } else {
4247 #ifndef MODEST_TOOLKIT_HILDON2
4248                         /* Set parent to NULL or the banner will disappear with its parent dialog */
4249                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
4250 #endif
4251                         completed = TRUE;
4252                         if (username)
4253                                 *username = NULL;
4254                         if (password)
4255                                 *password = NULL;
4256                         if (cancel)
4257                                 *cancel   = TRUE;
4258                 }
4259         }
4260
4261 /* This is not in the Maemo UI spec:
4262         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
4263                 *remember = TRUE;
4264         else
4265                 *remember = FALSE;
4266 */
4267
4268         g_free (initial_username);
4269         gtk_widget_destroy (dialog);
4270         g_slice_free (PasswordDialogFields, fields);
4271
4272         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
4273 }
4274
4275 void
4276 modest_ui_actions_on_cut (GtkAction *action,
4277                           ModestWindow *window)
4278 {
4279         GtkWidget *focused_widget;
4280         GtkClipboard *clipboard;
4281
4282         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4283         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4284         if (GTK_IS_EDITABLE (focused_widget)) {
4285                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
4286                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4287                 gtk_clipboard_store (clipboard);
4288         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4289                 GtkTextBuffer *buffer;
4290
4291                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4292                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4293                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
4294                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4295                         gtk_clipboard_store (clipboard);
4296                 }
4297         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4298                 TnyList *header_list = modest_header_view_get_selected_headers (
4299                                 MODEST_HEADER_VIEW (focused_widget));
4300                 gboolean continue_download = FALSE;
4301                 gint num_of_unc_msgs;
4302
4303                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4304
4305                 if (num_of_unc_msgs) {
4306                         TnyAccount *account = get_account_from_header_list (header_list);
4307                         if (account) {
4308                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4309                                 g_object_unref (account);
4310                         }
4311                 }
4312
4313                 if (num_of_unc_msgs == 0 || continue_download) {
4314 /*                      modest_platform_information_banner (
4315                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
4316                         modest_header_view_cut_selection (
4317                                         MODEST_HEADER_VIEW (focused_widget));
4318                 }
4319
4320                 g_object_unref (header_list);
4321         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4322                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
4323         }
4324 }
4325
4326 void
4327 modest_ui_actions_on_copy (GtkAction *action,
4328                            ModestWindow *window)
4329 {
4330         GtkClipboard *clipboard;
4331         GtkWidget *focused_widget;
4332         gboolean copied = TRUE;
4333
4334         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4335         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4336
4337         if (GTK_IS_LABEL (focused_widget)) {
4338                 gchar *selection;
4339                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
4340                 gtk_clipboard_set_text (clipboard, selection, -1);
4341                 g_free (selection);
4342                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4343                 gtk_clipboard_store (clipboard);
4344         } else if (GTK_IS_EDITABLE (focused_widget)) {
4345                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
4346                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4347                 gtk_clipboard_store (clipboard);
4348         } else if (GTK_IS_HTML (focused_widget)) {
4349                 const gchar *sel;
4350                 int len = -1;
4351                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
4352                 if ((sel == NULL) || (sel[0] == '\0')) {
4353                         copied = FALSE;
4354                 } else {
4355                         gtk_html_copy (GTK_HTML (focused_widget));
4356                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4357                         gtk_clipboard_store (clipboard);
4358                 }
4359         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4360                 GtkTextBuffer *buffer;
4361                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4362                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4363                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
4364                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4365                         gtk_clipboard_store (clipboard);
4366                 }
4367         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4368                 TnyList *header_list = modest_header_view_get_selected_headers (
4369                                 MODEST_HEADER_VIEW (focused_widget));
4370                 gboolean continue_download = FALSE;
4371                 gint num_of_unc_msgs;
4372
4373                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4374
4375                 if (num_of_unc_msgs) {
4376                         TnyAccount *account = get_account_from_header_list (header_list);
4377                         if (account) {
4378                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4379                                 g_object_unref (account);
4380                         }
4381                 }
4382
4383                 if (num_of_unc_msgs == 0 || continue_download) {
4384                         modest_platform_information_banner (
4385                                         NULL, NULL, _CS("mcen_ib_getting_items"));
4386                         modest_header_view_copy_selection (
4387                                         MODEST_HEADER_VIEW (focused_widget));
4388                 } else
4389                         copied = FALSE;
4390
4391                 g_object_unref (header_list);
4392
4393         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4394                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
4395         }
4396
4397         /* Show information banner if there was a copy to clipboard */
4398         if(copied)
4399                 modest_platform_information_banner (
4400                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
4401 }
4402
4403 void
4404 modest_ui_actions_on_undo (GtkAction *action,
4405                            ModestWindow *window)
4406 {
4407         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4408                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
4409 #ifndef MODEST_TOOLKIT_HILDON2
4410         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4411                 ModestEmailClipboard *clipboard = NULL;
4412                 /* Clear clipboard source */
4413                 clipboard = modest_runtime_get_email_clipboard ();
4414                 modest_email_clipboard_clear (clipboard);
4415 #endif
4416         } else {
4417                 g_return_if_reached ();
4418         }
4419 }
4420
4421 void
4422 modest_ui_actions_on_redo (GtkAction *action,
4423                            ModestWindow *window)
4424 {
4425         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4426                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
4427         }
4428         else {
4429                 g_return_if_reached ();
4430         }
4431 }
4432
4433
4434 static void
4435 destroy_information_note (ModestMailOperation *mail_op,
4436                           gpointer user_data)
4437 {
4438         /* destroy information note */
4439         gtk_widget_destroy (GTK_WIDGET(user_data));
4440 }
4441
4442 static void
4443 destroy_folder_information_note (ModestMailOperation *mail_op,
4444                                  TnyFolder *new_folder,
4445                                  gpointer user_data)
4446 {
4447         /* destroy information note */
4448         gtk_widget_destroy (GTK_WIDGET(user_data));
4449 }
4450
4451
4452 static void
4453 paste_as_attachment_free (gpointer data)
4454 {
4455         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
4456
4457         if (helper->banner) {
4458                 gtk_widget_destroy (helper->banner);
4459                 g_object_unref (helper->banner);
4460         }
4461         g_free (helper);
4462 }
4463
4464 static void
4465 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
4466                             TnyHeader *header,
4467                             TnyMsg *msg,
4468                             gpointer userdata)
4469 {
4470         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4471         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4472
4473         if (msg == NULL)
4474                 return;
4475
4476         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4477
4478 }
4479
4480 void
4481 modest_ui_actions_on_paste (GtkAction *action,
4482                             ModestWindow *window)
4483 {
4484         GtkWidget *focused_widget = NULL;
4485         GtkWidget *inf_note = NULL;
4486         ModestMailOperation *mail_op = NULL;
4487
4488         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4489         if (GTK_IS_EDITABLE (focused_widget)) {
4490                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4491         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4492                 ModestEmailClipboard *e_clipboard = NULL;
4493                 e_clipboard = modest_runtime_get_email_clipboard ();
4494                 if (modest_email_clipboard_cleared (e_clipboard)) {
4495                         GtkTextBuffer *buffer;
4496                         GtkClipboard *clipboard;
4497
4498                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4499                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4500                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4501                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4502                         ModestMailOperation *mail_op;
4503                         TnyFolder *src_folder = NULL;
4504                         TnyList *data = NULL;
4505                         gboolean delete;
4506                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4507                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4508                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4509                                                                            _CS("ckct_nw_pasting"));
4510                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4511                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4512                         if (helper->banner != NULL) {
4513                                 g_object_ref (G_OBJECT (helper->banner));
4514                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4515                         }
4516
4517                         if (data != NULL) {
4518                                 modest_mail_operation_get_msgs_full (mail_op,
4519                                                                      data,
4520                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4521                                                                      helper,
4522                                                                      paste_as_attachment_free);
4523                         }
4524                         /* Free */
4525                         if (data)
4526                                 g_object_unref (data);
4527                         if (src_folder)
4528                                 g_object_unref (src_folder);
4529
4530                 }
4531         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4532                 ModestEmailClipboard *clipboard = NULL;
4533                 TnyFolder *src_folder = NULL;
4534                 TnyFolderStore *folder_store = NULL;
4535                 TnyList *data = NULL;
4536                 gboolean delete = FALSE;
4537
4538                 /* Check clipboard source */
4539                 clipboard = modest_runtime_get_email_clipboard ();
4540                 if (modest_email_clipboard_cleared (clipboard))
4541                         return;
4542
4543                 /* Get elements to paste */
4544                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4545
4546                 /* Create a new mail operation */
4547                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4548
4549                 /* Get destination folder */
4550                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4551
4552                 /* transfer messages  */
4553                 if (data != NULL) {
4554                         gint response = 0;
4555
4556                         /* Ask for user confirmation */
4557                         response =
4558                                 modest_ui_actions_msgs_move_to_confirmation (window,
4559                                                                              TNY_FOLDER (folder_store),
4560                                                                              delete,
4561                                                                              data);
4562
4563                         if (response == GTK_RESPONSE_OK) {
4564                                 /* Launch notification */
4565                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4566                                                                              _CS("ckct_nw_pasting"));
4567                                 if (inf_note != NULL)  {
4568                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4569                                         gtk_widget_show (GTK_WIDGET(inf_note));
4570                                 }
4571
4572                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4573                                 modest_mail_operation_xfer_msgs (mail_op,
4574                                                                  data,
4575                                                                  TNY_FOLDER (folder_store),
4576                                                                  delete,
4577                                                                  destroy_information_note,
4578                                                                  inf_note);
4579                         } else {
4580                                 g_object_unref (mail_op);
4581                         }
4582
4583                 } else if (src_folder != NULL) {
4584                         /* Launch notification */
4585                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4586                                                                      _CS("ckct_nw_pasting"));
4587                         if (inf_note != NULL)  {
4588                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4589                                 gtk_widget_show (GTK_WIDGET(inf_note));
4590                         }
4591
4592                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4593                         modest_mail_operation_xfer_folder (mail_op,
4594                                                            src_folder,
4595                                                            folder_store,
4596                                                            delete,
4597                                                            destroy_folder_information_note,
4598                                                            inf_note);
4599                 }
4600
4601                 /* Free */
4602                 if (data != NULL)
4603                         g_object_unref (data);
4604                 if (src_folder != NULL)
4605                         g_object_unref (src_folder);
4606                 if (folder_store != NULL)
4607                         g_object_unref (folder_store);
4608         }
4609 }
4610
4611
4612 void
4613 modest_ui_actions_on_select_all (GtkAction *action,
4614                                  ModestWindow *window)
4615 {
4616         GtkWidget *focused_widget;
4617
4618         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4619         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4620                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4621         } else if (GTK_IS_LABEL (focused_widget)) {
4622                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4623         } else if (GTK_IS_EDITABLE (focused_widget)) {
4624                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4625         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4626                 GtkTextBuffer *buffer;
4627                 GtkTextIter start, end;
4628
4629                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4630                 gtk_text_buffer_get_start_iter (buffer, &start);
4631                 gtk_text_buffer_get_end_iter (buffer, &end);
4632                 gtk_text_buffer_select_range (buffer, &start, &end);
4633         } else if (GTK_IS_HTML (focused_widget)) {
4634                 gtk_html_select_all (GTK_HTML (focused_widget));
4635 #ifndef MODEST_TOOLKIT_HILDON2
4636         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4637                 GtkWidget *header_view = focused_widget;
4638                 GtkTreeSelection *selection = NULL;
4639
4640                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4641                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4642                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4643                 }
4644
4645                 /* Disable window dimming management */
4646                 modest_window_disable_dimming (MODEST_WINDOW(window));
4647
4648                 /* Select all messages */
4649                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4650                 gtk_tree_selection_select_all (selection);
4651
4652                 /* Set focuse on header view */
4653                 gtk_widget_grab_focus (header_view);
4654
4655                 /* Enable window dimming management */
4656                 modest_window_enable_dimming (MODEST_WINDOW(window));
4657                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4658                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4659 #endif
4660         }
4661
4662 }
4663
4664 void
4665 modest_ui_actions_on_mark_as_read (GtkAction *action,
4666                                    ModestWindow *window)
4667 {
4668         g_return_if_fail (MODEST_IS_WINDOW(window));
4669
4670         /* Mark each header as read */
4671         do_headers_action (window, headers_action_mark_as_read, NULL);
4672 }
4673
4674 void
4675 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4676                                      ModestWindow *window)
4677 {
4678         g_return_if_fail (MODEST_IS_WINDOW(window));
4679
4680         /* Mark each header as read */
4681         do_headers_action (window, headers_action_mark_as_unread, NULL);
4682 }
4683
4684 void
4685 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4686                                   GtkRadioAction *selected,
4687                                   ModestWindow *window)
4688 {
4689         gint value;
4690
4691         value = gtk_radio_action_get_current_value (selected);
4692         if (MODEST_IS_WINDOW (window)) {
4693                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4694         }
4695 }
4696
4697 void
4698 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4699                                                GtkRadioAction *selected,
4700                                                ModestWindow *window)
4701 {
4702         TnyHeaderFlags flags;
4703         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4704
4705         flags = gtk_radio_action_get_current_value (selected);
4706         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4707 }
4708
4709 void
4710 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4711                                                   GtkRadioAction *selected,
4712                                                   ModestWindow *window)
4713 {
4714         gint file_format;
4715
4716         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4717
4718         file_format = gtk_radio_action_get_current_value (selected);
4719         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4720 }
4721
4722
4723 void
4724 modest_ui_actions_on_zoom_plus (GtkAction *action,
4725                                 ModestWindow *window)
4726 {
4727         g_return_if_fail (MODEST_IS_WINDOW (window));
4728
4729         modest_window_zoom_plus (MODEST_WINDOW (window));
4730 }
4731
4732 void
4733 modest_ui_actions_on_zoom_minus (GtkAction *action,
4734                                  ModestWindow *window)
4735 {
4736         g_return_if_fail (MODEST_IS_WINDOW (window));
4737
4738         modest_window_zoom_minus (MODEST_WINDOW (window));
4739 }
4740
4741 void
4742 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4743                                            ModestWindow *window)
4744 {
4745         ModestWindowMgr *mgr;
4746         gboolean fullscreen, active;
4747         g_return_if_fail (MODEST_IS_WINDOW (window));
4748
4749         mgr = modest_runtime_get_window_mgr ();
4750
4751         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4752         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4753
4754         if (active != fullscreen) {
4755                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4756 #ifndef MODEST_TOOLKIT_HILDON2
4757                 gtk_window_present (GTK_WINDOW (window));
4758 #endif
4759         }
4760 }
4761
4762 void
4763 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4764                                         ModestWindow *window)
4765 {
4766         ModestWindowMgr *mgr;
4767         gboolean fullscreen;
4768
4769         g_return_if_fail (MODEST_IS_WINDOW (window));
4770
4771         mgr = modest_runtime_get_window_mgr ();
4772         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4773         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4774
4775 #ifndef MODEST_TOOLKIT_HILDON2
4776         gtk_window_present (GTK_WINDOW (window));
4777 #endif
4778 }
4779
4780 /*
4781  * Used by modest_ui_actions_on_details to call do_headers_action
4782  */
4783 static void
4784 headers_action_show_details (TnyHeader *header,
4785                              ModestWindow *window,
4786                              gpointer user_data)
4787
4788 {
4789         gboolean async_retrieval;
4790         TnyMsg *msg = NULL;
4791
4792         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4793                 async_retrieval = TRUE;
4794                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
4795         } else {
4796                 async_retrieval = FALSE;
4797         }
4798         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
4799         if (msg)
4800                 g_object_unref (msg);
4801 }
4802
4803 /*
4804  * Show the header details in a ModestDetailsDialog widget
4805  */
4806 void
4807 modest_ui_actions_on_details (GtkAction *action,
4808                               ModestWindow *win)
4809 {
4810         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4811                 TnyMsg *msg;
4812                 TnyHeader *header;
4813
4814                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4815                 if (!msg)
4816                         return;
4817
4818                 header = tny_msg_get_header (msg);
4819                 if (header) {
4820                         headers_action_show_details (header, win, NULL);
4821                         g_object_unref (header);
4822                 }
4823                 g_object_unref (msg);
4824 #ifndef MODEST_TOOLKIT_HILDON2
4825         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4826                 GtkWidget *folder_view, *header_view;
4827
4828                 /* Check which widget has the focus */
4829                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4830                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4831                 if (gtk_widget_is_focus (folder_view)) {
4832                         TnyFolderStore *folder_store
4833                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4834                         if (!folder_store) {
4835                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4836                                 return;
4837                         }
4838                         /* Show only when it's a folder */
4839                         /* This function should not be called for account items,
4840                          * because we dim the menu item for them. */
4841                         if (TNY_IS_FOLDER (folder_store)) {
4842                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4843                                                                            TNY_FOLDER (folder_store));
4844                         }
4845
4846                         g_object_unref (folder_store);
4847
4848                 } else {
4849                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4850                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4851                         /* Show details of each header */
4852                         do_headers_action (win, headers_action_show_details, header_view);
4853                 }
4854 #else
4855         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4856                 TnyFolder *folder;
4857                 GtkWidget *header_view;
4858
4859                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4860                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4861                 if (folder) {
4862                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4863                                                                    folder);
4864                         g_object_unref (folder);
4865                 }
4866 #endif
4867         }
4868 }
4869
4870 void
4871 modest_ui_actions_on_limit_error (GtkAction *action,
4872                                   ModestWindow *win)
4873 {
4874         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
4875
4876         modest_platform_information_banner ((GtkWidget *) win, NULL, _CS("ckdg_ib_maximum_characters_reached"));
4877
4878 }
4879
4880 void
4881 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4882                                      ModestMsgEditWindow *window)
4883 {
4884         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4885
4886         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4887 }
4888
4889 void
4890 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4891                                       ModestMsgEditWindow *window)
4892 {
4893         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4894
4895         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4896 }
4897
4898 #ifndef MODEST_TOOLKIT_HILDON2
4899 void
4900 modest_ui_actions_toggle_folders_view (GtkAction *action,
4901                                        ModestMainWindow *main_window)
4902 {
4903         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4904
4905         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4906                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4907         else
4908                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4909 }
4910 #endif
4911
4912 void
4913 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4914                                      ModestWindow *window)
4915 {
4916         gboolean active, fullscreen = FALSE;
4917         ModestWindowMgr *mgr;
4918
4919         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4920
4921         /* Check if we want to toggle the toolbar view in fullscreen
4922            or normal mode */
4923         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4924                      "ViewShowToolbarFullScreen")) {
4925                 fullscreen = TRUE;
4926         }
4927
4928         /* Toggle toolbar */
4929         mgr = modest_runtime_get_window_mgr ();
4930         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4931 }
4932
4933 void
4934 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4935                                            ModestMsgEditWindow *window)
4936 {
4937         modest_msg_edit_window_select_font (window);
4938 }
4939
4940
4941 void
4942 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4943                                                   const gchar *display_name,
4944                                                   GtkWindow *window)
4945 {
4946         /* don't update the display name if it was already set;
4947          * updating the display name apparently is expensive */
4948         const gchar* old_name = gtk_window_get_title (window);
4949
4950         if (display_name == NULL)
4951                 display_name = " ";
4952
4953         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4954                 return; /* don't do anything */
4955
4956         /* This is usually used to change the title of the main window, which
4957          * is the one that holds the folder view. Note that this change can
4958          * happen even when the widget doesn't have the focus. */
4959         gtk_window_set_title (window, display_name);
4960
4961 }
4962
4963 void
4964 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4965 {
4966         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4967         modest_msg_edit_window_select_contacts (window);
4968 }
4969
4970 void
4971 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4972 {
4973         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4974         modest_msg_edit_window_check_names (window, FALSE);
4975 }
4976
4977 #ifndef MODEST_TOOLKIT_HILDON2
4978 /*
4979  * This function is used to track changes in the selection of the
4980  * folder view that is inside the "move to" dialog to enable/disable
4981  * the OK button because we do not want the user to select a disallowed
4982  * destination for a folder.
4983  * The user also not desired to be able to use NEW button on items where
4984  * folder creation is not possibel.
4985  */
4986 static void
4987 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4988                                             TnyFolderStore *folder_store,
4989                                             gboolean selected,
4990                                             gpointer user_data)
4991 {
4992         GtkWidget *dialog = NULL;
4993         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4994         gboolean moving_folder = FALSE;
4995         gboolean is_local_account = TRUE;
4996         GtkWidget *folder_view = NULL;
4997         ModestTnyFolderRules rules;
4998
4999         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
5000
5001         if (!selected)
5002                 return;
5003
5004         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
5005         if (!dialog)
5006                 return;
5007
5008         /* check if folder_store is an remote account */
5009         if (TNY_IS_ACCOUNT (folder_store)) {
5010                 TnyAccount *local_account = NULL;
5011                 TnyAccount *mmc_account = NULL;
5012                 ModestTnyAccountStore *account_store = NULL;
5013
5014                 account_store = modest_runtime_get_account_store ();
5015                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
5016                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
5017
5018                 if ((gpointer) local_account != (gpointer) folder_store &&
5019                     (gpointer) mmc_account != (gpointer) folder_store) {
5020                         ModestProtocolType proto;
5021                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
5022                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
5023                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
5024                         }
5025                         is_local_account = FALSE;
5026                         /* New button should be dimmed on remote
5027                            POP account root */
5028                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5029                                                                                          proto,
5030                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
5031                 }
5032                 g_object_unref (local_account);
5033
5034                 /* It could not exist */
5035                 if (mmc_account)
5036                         g_object_unref (mmc_account);
5037         }
5038
5039         /* Check the target folder rules */
5040         if (TNY_IS_FOLDER (folder_store)) {
5041                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
5042                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
5043                         ok_sensitive = FALSE;
5044                         new_sensitive = FALSE;
5045                         goto end;
5046                 }
5047         }
5048
5049         /* Check if we're moving a folder */
5050         if (MODEST_IS_MAIN_WINDOW (user_data)) {
5051                 /* Get the widgets */
5052                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
5053                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5054                 if (gtk_widget_is_focus (folder_view))
5055                         moving_folder = TRUE;
5056         }
5057
5058         if (moving_folder) {
5059                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
5060
5061                 /* Get the folder to move */
5062                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5063
5064                 /* Check that we're not moving to the same folder */
5065                 if (TNY_IS_FOLDER (moved_folder)) {
5066                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
5067                         if (parent == folder_store)
5068                                 ok_sensitive = FALSE;
5069                         g_object_unref (parent);
5070                 }
5071
5072                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
5073                         /* Do not allow to move to an account unless it's the
5074                            local folders account */
5075                         if (!is_local_account)
5076                                 ok_sensitive = FALSE;
5077                 }
5078
5079                 if (ok_sensitive && (moved_folder == folder_store)) {
5080                         /* Do not allow to move to itself */
5081                         ok_sensitive = FALSE;
5082                 }
5083                 g_object_unref (moved_folder);
5084         } else {
5085                 TnyFolder *src_folder = NULL;
5086
5087                 /* Moving a message */
5088                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
5089
5090                         TnyHeader *header = NULL;
5091                         header = modest_msg_view_window_get_header
5092                                 (MODEST_MSG_VIEW_WINDOW (user_data));
5093                         if (!TNY_IS_HEADER(header))
5094                                 g_warning ("%s: could not get source header", __FUNCTION__);
5095                         else
5096                                 src_folder = tny_header_get_folder (header);
5097
5098                         if (header)
5099                                 g_object_unref (header);
5100                 } else {
5101                         src_folder =
5102                                 TNY_FOLDER (modest_folder_view_get_selected
5103                                             (MODEST_FOLDER_VIEW (folder_view)));
5104                 }
5105
5106                 if (TNY_IS_FOLDER(src_folder)) {
5107                         /* Do not allow to move the msg to the same folder */
5108                         /* Do not allow to move the msg to an account */
5109                         if ((gpointer) src_folder == (gpointer) folder_store ||
5110                             TNY_IS_ACCOUNT (folder_store))
5111                                 ok_sensitive = FALSE;
5112                         g_object_unref (src_folder);
5113                 } else
5114                         g_warning ("%s: could not get source folder", __FUNCTION__);
5115         }
5116
5117  end:
5118         /* Set sensitivity of the OK and NEW button */
5119         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
5120         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
5121 }
5122 #endif
5123
5124 static void
5125 on_move_to_dialog_response (GtkDialog *dialog,
5126                             gint       response,
5127                             gpointer   user_data)
5128 {
5129         GtkWidget *parent_win;
5130         MoveToInfo *helper = NULL;
5131         ModestFolderView *folder_view;
5132         gboolean unset_edit_mode = FALSE;
5133
5134         helper = (MoveToInfo *) user_data;
5135
5136         parent_win = (GtkWidget *) helper->win;
5137         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
5138                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
5139         switch (response) {
5140                 TnyFolderStore *dst_folder;
5141                 TnyFolderStore *selected;
5142
5143         case MODEST_GTK_RESPONSE_NEW_FOLDER:
5144                 selected = modest_folder_view_get_selected (folder_view);
5145                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view), selected);
5146                 g_object_unref (selected);
5147                 return;
5148         case GTK_RESPONSE_NONE:
5149         case GTK_RESPONSE_CANCEL:
5150         case GTK_RESPONSE_DELETE_EVENT:
5151                 break;
5152         case GTK_RESPONSE_OK:
5153                 dst_folder = modest_folder_view_get_selected (folder_view);
5154
5155 #ifndef MODEST_TOOLKIT_HILDON2
5156                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
5157                         /* Clean list to move used for filtering */
5158                         modest_folder_view_set_list_to_move (folder_view, NULL);
5159
5160                         modest_ui_actions_on_main_window_move_to (NULL,
5161                                                                   GTK_WIDGET (folder_view),
5162                                                                   dst_folder,
5163                                                                   MODEST_MAIN_WINDOW (parent_win));
5164 #else
5165                 if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
5166                         /* Clean list to move used for filtering */
5167                         modest_folder_view_set_list_to_move (folder_view, NULL);
5168
5169                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
5170                                                                     dst_folder,
5171                                                                     helper->list,
5172                                                                     GTK_WINDOW (parent_win));
5173 #endif
5174                 } else {
5175                         /* if the user selected a root folder
5176                            (account) then do not perform any action */
5177                         if (TNY_IS_ACCOUNT (dst_folder)) {
5178                                 g_signal_stop_emission_by_name (dialog, "response");
5179                                 return;
5180                         }
5181
5182                         /* Clean list to move used for filtering */
5183                         modest_folder_view_set_list_to_move (folder_view, NULL);
5184
5185                         /* Moving from headers window in edit mode */
5186                         modest_ui_actions_on_window_move_to (NULL, helper->list,
5187                                                              dst_folder,
5188                                                              MODEST_WINDOW (parent_win));
5189                 }
5190
5191                 if (dst_folder)
5192                         g_object_unref (dst_folder);
5193
5194                 unset_edit_mode = TRUE;
5195                 break;
5196         default:
5197                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
5198         }
5199
5200         /* Free the helper and exit */
5201         if (helper->list)
5202                 g_object_unref (helper->list);
5203         if (unset_edit_mode) {
5204 #ifdef MODEST_TOOLKIT_HILDON2
5205                 modest_hildon2_window_unset_edit_mode (MODEST_HILDON2_WINDOW (helper->win));
5206 #endif
5207         }
5208         g_slice_free (MoveToInfo, helper);
5209         gtk_widget_destroy (GTK_WIDGET (dialog));
5210 }
5211
5212 static GtkWidget*
5213 create_move_to_dialog (GtkWindow *win,
5214                        GtkWidget *folder_view,
5215                        TnyList *list_to_move)
5216 {
5217         GtkWidget *dialog, *tree_view = NULL;
5218
5219         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
5220
5221 #ifndef MODEST_TOOLKIT_HILDON2
5222         /* Track changes in the selection to
5223          * disable the OK button whenever "Move to" is not possible
5224          * disbale NEW button whenever New is not possible */
5225         g_signal_connect (tree_view,
5226                           "folder_selection_changed",
5227                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
5228                           win);
5229 #endif
5230
5231         /* It could happen that we're trying to move a message from a
5232            window (msg window for example) after the main window was
5233            closed, so we can not just get the model of the folder
5234            view */
5235         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
5236                 const gchar *visible_id = NULL;
5237
5238                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5239                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5240                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
5241                                                MODEST_FOLDER_VIEW(tree_view));
5242
5243                 visible_id =
5244                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
5245
5246                 /* Show the same account than the one that is shown in the main window */
5247                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
5248                                                                              visible_id);
5249         } else {
5250                 const gchar *active_account_name = NULL;
5251                 ModestAccountMgr *mgr = NULL;
5252                 ModestAccountSettings *settings = NULL;
5253                 ModestServerAccountSettings *store_settings = NULL;
5254
5255                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5256                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5257                 /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view), */
5258                 /*                               TNY_ACCOUNT_STORE (modest_runtime_get_account_store ())); */
5259
5260                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
5261                 mgr = modest_runtime_get_account_mgr ();
5262                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
5263
5264                 if (settings) {
5265                         const gchar *store_account_name;
5266                         store_settings = modest_account_settings_get_store_settings (settings);
5267                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
5268
5269                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
5270                                                                                      store_account_name);
5271                         g_object_unref (store_settings);
5272                         g_object_unref (settings);
5273                 }
5274         }
5275
5276         /* we keep a pointer to the embedded folder view, so we can
5277          *   retrieve it with get_folder_view_from_move_to_dialog (see
5278          *   above) later (needed for focus handling)
5279          */
5280         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
5281
5282         /* Hide special folders */
5283 #ifndef MODEST_TOOLKIT_HILDON2
5284         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
5285 #endif
5286         if (list_to_move)
5287                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
5288 #ifndef MODEST_TOOLKIT_HILDON2
5289         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5290 #endif
5291
5292         gtk_widget_show (GTK_WIDGET (tree_view));
5293
5294         return dialog;
5295 }
5296
5297 /*
5298  * Shows a confirmation dialog to the user when we're moving messages
5299  * from a remote server to the local storage. Returns the dialog
5300  * response. If it's other kind of movement then it always returns
5301  * GTK_RESPONSE_OK
5302  *
5303  * This one is used by the next functions:
5304  *      modest_ui_actions_on_paste                      - commented out
5305  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
5306  */
5307 gint
5308 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
5309                                              TnyFolder *dest_folder,
5310                                              gboolean delete,
5311                                              TnyList *headers)
5312 {
5313         gint response = GTK_RESPONSE_OK;
5314         TnyAccount *account = NULL;
5315         TnyFolder *src_folder = NULL;
5316         TnyIterator *iter = NULL;
5317         TnyHeader *header = NULL;
5318
5319         /* return with OK if the destination is a remote folder */
5320         if (modest_tny_folder_is_remote_folder (dest_folder))
5321                 return GTK_RESPONSE_OK;
5322
5323         /* Get source folder */
5324         iter = tny_list_create_iterator (headers);
5325         header = TNY_HEADER (tny_iterator_get_current (iter));
5326         if (header) {
5327                 src_folder = tny_header_get_folder (header);
5328                 g_object_unref (header);
5329         }
5330         g_object_unref (iter);
5331
5332         /* if no src_folder, message may be an attahcment */
5333         if (src_folder == NULL)
5334                 return GTK_RESPONSE_CANCEL;
5335
5336         /* If the source is a local or MMC folder */
5337         if (!modest_tny_folder_is_remote_folder (src_folder)) {
5338                 g_object_unref (src_folder);
5339                 return GTK_RESPONSE_OK;
5340         }
5341
5342         /* Get the account */
5343         account = tny_folder_get_account (src_folder);
5344
5345         /* now if offline we ask the user */
5346         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
5347                 response = GTK_RESPONSE_OK;
5348         else
5349                 response = GTK_RESPONSE_CANCEL;
5350
5351         /* Frees */
5352         g_object_unref (src_folder);
5353         g_object_unref (account);
5354
5355         return response;
5356 }
5357
5358 static void
5359 move_to_helper_destroyer (gpointer user_data)
5360 {
5361         MoveToHelper *helper = (MoveToHelper *) user_data;
5362
5363         /* Close the "Pasting" information banner */
5364         if (helper->banner) {
5365                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
5366                 g_object_unref (helper->banner);
5367         }
5368         if (gtk_tree_row_reference_valid (helper->reference)) {
5369                 gtk_tree_row_reference_free (helper->reference);
5370                 helper->reference = NULL;
5371         }
5372         g_free (helper);
5373 }
5374
5375 static void
5376 move_to_cb (ModestMailOperation *mail_op,
5377             gpointer user_data)
5378 {
5379         MoveToHelper *helper = (MoveToHelper *) user_data;
5380         GObject *object = modest_mail_operation_get_source (mail_op);
5381
5382         /* Note that the operation could have failed, in that case do
5383            nothing */
5384         if (modest_mail_operation_get_status (mail_op) !=
5385             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5386                 goto frees;
5387
5388         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
5389                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
5390
5391                 if (!modest_msg_view_window_select_next_message (self) &&
5392                     !modest_msg_view_window_select_previous_message (self)) {
5393                         /* No more messages to view, so close this window */
5394                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
5395                 }
5396 #ifndef MODEST_TOOLKIT_HILDON2
5397         } else if (MODEST_IS_MAIN_WINDOW (object) &&
5398                    gtk_tree_row_reference_valid (helper->reference)) {
5399                 GtkWidget *header_view;
5400                 GtkTreePath *path;
5401                 GtkTreeSelection *sel;
5402
5403                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5404                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5405                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
5406                 path = gtk_tree_row_reference_get_path (helper->reference);
5407                 /* We need to unselect the previous one
5408                    because we could be copying instead of
5409                    moving */
5410                 gtk_tree_selection_unselect_all (sel);
5411                 gtk_tree_selection_select_path (sel, path);
5412                 gtk_tree_path_free (path);
5413 #endif
5414         }
5415         g_object_unref (object);
5416
5417  frees:
5418         /* Destroy the helper */
5419         move_to_helper_destroyer (helper);
5420 }
5421
5422 static void
5423 folder_move_to_cb (ModestMailOperation *mail_op,
5424                    TnyFolder *new_folder,
5425                    gpointer user_data)
5426 {
5427         GObject *object;
5428
5429         object = modest_mail_operation_get_source (mail_op);
5430 #ifndef MODEST_TOOLKIT_HILDON2
5431         if (MODEST_IS_MAIN_WINDOW (object)) {
5432                 GtkWidget *folder_view;
5433                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5434                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5435                 g_object_ref (folder_view);
5436                 g_object_unref (object);
5437                 move_to_cb (mail_op, user_data);
5438                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5439                 g_object_unref (folder_view);
5440         } else {
5441 #else
5442                 {
5443 #endif
5444                 move_to_cb (mail_op, user_data);
5445         }
5446 }
5447
5448 static void
5449 msgs_move_to_cb (ModestMailOperation *mail_op,
5450                  gpointer user_data)
5451 {
5452         move_to_cb (mail_op, user_data);
5453 }
5454
5455 void
5456 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
5457                                              gpointer user_data)
5458 {
5459         GObject *win = NULL;
5460         const GError *error;
5461         TnyAccount *account = NULL;
5462
5463 #ifndef MODEST_TOOLKIT_HILDON2
5464         ModestWindow *main_window = NULL;
5465
5466         /* Disable next automatic folder selection */
5467         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5468                                                          FALSE); /* don't create */
5469
5470         /* Show notification dialog only if the main window exists */
5471         if (main_window) {
5472                 GtkWidget *folder_view = NULL;
5473
5474                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5475                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5476                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5477
5478                 if (user_data && TNY_IS_FOLDER (user_data)) {
5479                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
5480                                                           TNY_FOLDER (user_data), FALSE);
5481                 }
5482         }
5483 #endif
5484         win = modest_mail_operation_get_source (mail_op);
5485         error = modest_mail_operation_get_error (mail_op);
5486
5487         if (TNY_IS_FOLDER (user_data))
5488                 account = modest_tny_folder_get_account (TNY_FOLDER (user_data));
5489         else if (TNY_IS_ACCOUNT (user_data))
5490                 account = g_object_ref (user_data);
5491
5492         /* If it's not a disk full error then show a generic error */
5493         if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5494                                                              (GtkWidget *) win, (GError *) error,
5495                                                              account, NULL))
5496                 modest_platform_run_information_dialog ((GtkWindow *) win,
5497                                                         _("mail_in_ui_folder_move_target_error"),
5498                                                         FALSE);
5499         if (account)
5500                 g_object_unref (account);
5501         if (win)
5502                 g_object_unref (win);
5503 }
5504
5505 #ifndef MODEST_TOOLKIT_HILDON2
5506 static void
5507 open_msg_for_purge_cb (ModestMailOperation *mail_op,
5508                        TnyHeader *header,
5509                        gboolean canceled,
5510                        TnyMsg *msg,
5511                        GError *err,
5512                        gpointer user_data)
5513 {
5514         TnyList *parts;
5515         TnyIterator *iter;
5516         gint pending_purges = 0;
5517         gboolean some_purged = FALSE;
5518         ModestWindow *win = MODEST_WINDOW (user_data);
5519         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5520
5521         /* If there was any error */
5522         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5523                 modest_window_mgr_unregister_header (mgr, header);
5524                 return;
5525         }
5526
5527         /* Once the message has been retrieved for purging, we check if
5528          * it's all ok for purging */
5529
5530         parts = tny_simple_list_new ();
5531         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5532         iter = tny_list_create_iterator (parts);
5533
5534         while (!tny_iterator_is_done (iter)) {
5535                 TnyMimePart *part;
5536                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5537                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5538                         if (tny_mime_part_is_purged (part))
5539                                 some_purged = TRUE;
5540                         else
5541                                 pending_purges++;
5542                 }
5543
5544                 if (part)
5545                         g_object_unref (part);
5546
5547                 tny_iterator_next (iter);
5548         }
5549         g_object_unref (iter);
5550
5551
5552         if (pending_purges>0) {
5553                 gint response;
5554                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5555
5556                 if (response == GTK_RESPONSE_OK) {
5557                         GtkWidget *info;
5558                         info =
5559                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5560                         iter = tny_list_create_iterator (parts);
5561                         while (!tny_iterator_is_done (iter)) {
5562                                 TnyMimePart *part;
5563
5564                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5565                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5566                                         tny_mime_part_set_purged (part);
5567
5568                                 if (part)
5569                                         g_object_unref (part);
5570
5571                                 tny_iterator_next (iter);
5572                         }
5573                         g_object_unref (iter);
5574
5575                         tny_msg_rewrite_cache (msg);
5576
5577                         gtk_widget_destroy (info);
5578                 }
5579         }
5580
5581         modest_window_mgr_unregister_header (mgr, header);
5582
5583         g_object_unref (parts);
5584 }
5585
5586 static void
5587 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5588                                                      ModestMainWindow *win)
5589 {
5590         GtkWidget *header_view;
5591         TnyList *header_list;
5592         TnyHeader *header;
5593         TnyHeaderFlags flags;
5594         ModestWindow *msg_view_window =  NULL;
5595         gboolean found;
5596
5597         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5598
5599         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5600                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5601
5602         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5603         if (!header_list) {
5604                 g_warning ("%s: no header selected", __FUNCTION__);
5605                 return;
5606         }
5607
5608         if (tny_list_get_length (header_list) == 1) {
5609                 TnyIterator *iter = tny_list_create_iterator (header_list);
5610                 header = TNY_HEADER (tny_iterator_get_current (iter));
5611                 g_object_unref (iter);
5612         } else
5613                 return;
5614
5615         if (!header || !TNY_IS_HEADER(header)) {
5616                 g_warning ("%s: header is not valid", __FUNCTION__);
5617                 return;
5618         }
5619
5620         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5621                                                           header, &msg_view_window);
5622         flags = tny_header_get_flags (header);
5623         if (!(flags & TNY_HEADER_FLAG_CACHED))
5624                 return;
5625         if (found) {
5626                 if (msg_view_window != NULL)
5627                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5628                 else {
5629                         /* do nothing; uid was registered before, so window is probably on it's way */
5630                         g_debug ("header %p has already been registered", header);
5631                 }
5632         } else {
5633                 ModestMailOperation *mail_op = NULL;
5634                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5635                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5636                                                                          modest_ui_actions_disk_operations_error_handler,
5637                                                                          NULL, NULL);
5638                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5639                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5640
5641                 g_object_unref (mail_op);
5642         }
5643         if (header)
5644                 g_object_unref (header);
5645         if (header_list)
5646                 g_object_unref (header_list);
5647 }
5648 #endif
5649
5650 /*
5651  * Checks if we need a connection to do the transfer and if the user
5652  * wants to connect to complete it
5653  */
5654 static void
5655 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5656                                        TnyFolderStore *src_folder,
5657                                        TnyList *headers,
5658                                        TnyFolder *dst_folder,
5659                                        gboolean delete_originals,
5660                                        gboolean *need_connection,
5661                                        gboolean *do_xfer)
5662 {
5663         TnyAccount *src_account;
5664         gint uncached_msgs = 0;
5665
5666         /* We don't need any further check if
5667          *
5668          * 1- the source folder is local OR
5669          * 2- the device is already online
5670          */
5671         if (!modest_tny_folder_store_is_remote (src_folder) ||
5672             tny_device_is_online (modest_runtime_get_device())) {
5673                 *need_connection = FALSE;
5674                 *do_xfer = TRUE;
5675                 return;
5676         }
5677
5678         /* We must ask for a connection when
5679          *
5680          *   - the message(s) is not already cached   OR
5681          *   - the message(s) is cached but the leave_on_server setting
5682          * is FALSE (because we need to sync the source folder to
5683          * delete the message from the server (for IMAP we could do it
5684          * offline, it'll take place the next time we get a
5685          * connection)
5686          */
5687         uncached_msgs = header_list_count_uncached_msgs (headers);
5688         src_account = get_account_from_folder_store (src_folder);
5689         if (uncached_msgs > 0) {
5690                 guint num_headers;
5691                 const gchar *msg;
5692
5693                 *need_connection = TRUE;
5694                 num_headers = tny_list_get_length (headers);
5695                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5696
5697                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5698                     GTK_RESPONSE_CANCEL) {
5699                         *do_xfer = FALSE;
5700                 } else {
5701                         *do_xfer = TRUE;
5702                 }
5703         } else {
5704                 /* The transfer is possible and the user wants to */
5705                 *do_xfer = TRUE;
5706
5707                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5708                         const gchar *account_name;
5709                         gboolean leave_on_server;
5710
5711                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5712                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5713                                                                                   account_name);
5714
5715                         if (leave_on_server == TRUE) {
5716                                 *need_connection = FALSE;
5717                         } else {
5718                                 *need_connection = TRUE;
5719                         }
5720                 } else {
5721                         *need_connection = FALSE;
5722                 }
5723         }
5724
5725         /* Frees */
5726         g_object_unref (src_account);
5727 }
5728
5729 static void
5730 xfer_messages_error_handler (ModestMailOperation *mail_op,
5731                              gpointer user_data)
5732 {
5733         GObject *win;
5734         const GError *error;
5735         TnyAccount *account;
5736
5737         win = modest_mail_operation_get_source (mail_op);
5738         error = modest_mail_operation_get_error (mail_op);
5739
5740         /* We cannot get the account from the mail op as that is the
5741            source account and for checking memory full conditions we
5742            need the destination one */
5743         account = TNY_ACCOUNT (user_data);
5744
5745         if (error &&
5746             !modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5747                                                              (GtkWidget *) win, (GError*) error,
5748                                                              account, _KR("cerm_memory_card_full"))) {
5749                 modest_platform_run_information_dialog ((GtkWindow *) win,
5750                                                         _("mail_in_ui_folder_move_target_error"),
5751                                                         FALSE);
5752         }
5753         if (win)
5754                 g_object_unref (win);
5755 }
5756
5757 typedef struct {
5758         TnyFolderStore *dst_folder;
5759         TnyList *headers;
5760 } XferMsgsHelper;
5761
5762 /**
5763  * Utility function that transfer messages from both the main window
5764  * and the msg view window when using the "Move to" dialog
5765  */
5766 static void
5767 xfer_messages_performer  (gboolean canceled,
5768                           GError *err,
5769                           GtkWindow *parent_window,
5770                           TnyAccount *account,
5771                           gpointer user_data)
5772 {
5773         ModestWindow *win = MODEST_WINDOW (parent_window);
5774         TnyAccount *dst_account = NULL;
5775         gboolean dst_forbids_message_add = FALSE;
5776         XferMsgsHelper *helper;
5777         MoveToHelper *movehelper;
5778         ModestMailOperation *mail_op;
5779
5780         helper = (XferMsgsHelper *) user_data;
5781
5782         if (canceled || err) {
5783                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5784                                                                      (GtkWidget *) parent_window, err,
5785                                                                      account, NULL)) {
5786                         /* Show the proper error message */
5787                         modest_ui_actions_on_account_connection_error (parent_window, account);
5788                 }
5789                 goto end;
5790         }
5791
5792         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5793
5794         /* tinymail will return NULL for local folders it seems */
5795         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5796                                                                                   modest_tny_account_get_protocol_type (dst_account),
5797                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
5798
5799         if (dst_forbids_message_add) {
5800                 modest_platform_information_banner (GTK_WIDGET (win),
5801                                                     NULL,
5802                                                     ngettext("mail_in_ui_folder_move_target_error",
5803                                                              "mail_in_ui_folder_move_targets_error",
5804                                                              tny_list_get_length (helper->headers)));
5805                 goto end;
5806         }
5807
5808         movehelper = g_new0 (MoveToHelper, 1);
5809
5810 #ifndef MODEST_TOOLKIT_HILDON2
5811         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5812                                                                _CS("ckct_nw_pasting"));
5813         if (movehelper->banner != NULL)  {
5814                 g_object_ref (movehelper->banner);
5815                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5816         }
5817
5818         if (MODEST_IS_MAIN_WINDOW (win)) {
5819                 GtkWidget *header_view =
5820                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5821                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5822                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5823         }
5824 #endif
5825
5826         /* Perform the mail operation */
5827         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5828                                                                  xfer_messages_error_handler,
5829                                                                  g_object_ref (dst_account),
5830                                                                  g_object_unref);
5831         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5832                                          mail_op);
5833
5834         modest_mail_operation_xfer_msgs (mail_op,
5835                                          helper->headers,
5836                                          TNY_FOLDER (helper->dst_folder),
5837                                          TRUE,
5838                                          msgs_move_to_cb,
5839                                          movehelper);
5840
5841         g_object_unref (G_OBJECT (mail_op));
5842  end:
5843         if (dst_account)
5844                 g_object_unref (dst_account);
5845         g_object_unref (helper->dst_folder);
5846         g_object_unref (helper->headers);
5847         g_slice_free (XferMsgsHelper, helper);
5848 }
5849
5850 typedef struct {
5851         TnyFolder *src_folder;
5852         TnyFolderStore *dst_folder;
5853         gboolean delete_original;
5854         GtkWidget *folder_view;
5855 } MoveFolderInfo;
5856
5857 static void
5858 on_move_folder_cb (gboolean canceled,
5859                    GError *err,
5860                    GtkWindow *parent_window,
5861                    TnyAccount *account,
5862                    gpointer user_data)
5863 {
5864         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5865         GtkTreeSelection *sel;
5866         ModestMailOperation *mail_op = NULL;
5867
5868         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
5869                 /* Note that the connection process can fail due to
5870                    memory low conditions as it can not successfully
5871                    store the summary */
5872                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5873                                                                      (GtkWidget*) parent_window, err,
5874                                                                      account, NULL))
5875                         g_debug ("Error connecting when trying to move a folder");
5876
5877                 g_object_unref (G_OBJECT (info->src_folder));
5878                 g_object_unref (G_OBJECT (info->dst_folder));
5879                 g_free (info);
5880                 return;
5881         }
5882
5883         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5884 #ifndef MODEST_TOOLKIT_HILDON2
5885         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5886                         _CS("ckct_nw_pasting"));
5887         if (helper->banner != NULL)  {
5888                 g_object_ref (helper->banner);
5889                 gtk_widget_show (GTK_WIDGET(helper->banner));
5890         }
5891 #endif
5892         /* Clean folder on header view before moving it */
5893         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5894         gtk_tree_selection_unselect_all (sel);
5895
5896         /* Let gtk events run. We need that the folder
5897            view frees its reference to the source
5898            folder *before* issuing the mail operation
5899            so we need the signal handler of selection
5900            changed to happen before the mail
5901            operation
5902         while (gtk_events_pending ())
5903                 gtk_main_iteration ();   */
5904
5905         mail_op =
5906                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5907                                                                modest_ui_actions_move_folder_error_handler,
5908                                                                g_object_ref (info->dst_folder), g_object_unref);
5909         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5910                                          mail_op);
5911
5912 #ifndef MODEST_TOOLKIT_HILDON2
5913         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
5914                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5915                                                   TNY_FOLDER (info->dst_folder), TRUE);
5916         }
5917 #endif
5918         modest_mail_operation_xfer_folder (mail_op,
5919                         TNY_FOLDER (info->src_folder),
5920                         info->dst_folder,
5921                         info->delete_original,
5922                         folder_move_to_cb,
5923                         helper);
5924         g_object_unref (G_OBJECT (info->src_folder));
5925
5926         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5927         /* } */
5928
5929         /* Unref mail operation */
5930         g_object_unref (G_OBJECT (mail_op));
5931         g_object_unref (G_OBJECT (info->dst_folder));
5932         g_free (user_data);
5933 }
5934
5935 static TnyAccount *
5936 get_account_from_folder_store (TnyFolderStore *folder_store)
5937 {
5938         if (TNY_IS_ACCOUNT (folder_store))
5939                 return g_object_ref (folder_store);
5940         else
5941                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5942 }
5943
5944 #ifndef MODEST_TOOLKIT_HILDON2
5945 /*
5946  * UI handler for the "Move to" action when invoked from the
5947  * ModestMainWindow
5948  */
5949 static void
5950 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5951                                           GtkWidget *folder_view,
5952                                           TnyFolderStore *dst_folder,
5953                                           ModestMainWindow *win)
5954 {
5955         ModestHeaderView *header_view = NULL;
5956         TnyFolderStore *src_folder = NULL;
5957
5958         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5959
5960         /* Get the source folder */
5961         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5962
5963         /* Get header view */
5964         header_view = (ModestHeaderView *)
5965                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5966
5967         /* Get folder or messages to transfer */
5968         if (gtk_widget_is_focus (folder_view)) {
5969                 gboolean do_xfer = TRUE;
5970
5971                 /* Allow only to transfer folders to the local root folder */
5972                 if (TNY_IS_ACCOUNT (dst_folder) &&
5973                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5974                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5975                         do_xfer = FALSE;
5976                 } else if (!TNY_IS_FOLDER (src_folder)) {
5977                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5978                         do_xfer = FALSE;
5979                 }
5980
5981                 if (do_xfer) {
5982                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5983                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5984
5985                         info->src_folder = g_object_ref (src_folder);
5986                         info->dst_folder = g_object_ref (dst_folder);
5987                         info->delete_original = TRUE;
5988                         info->folder_view = folder_view;
5989
5990                         connect_info->callback = on_move_folder_cb;
5991                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5992                         connect_info->data = info;
5993
5994                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5995                                                                    TNY_FOLDER_STORE (src_folder),
5996                                                                    connect_info);
5997                 }
5998         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5999                 TnyList *headers;
6000
6001                 headers = modest_header_view_get_selected_headers(header_view);
6002
6003                 /* Transfer the messages */
6004                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
6005                                                             headers, TNY_FOLDER (dst_folder));
6006
6007                 g_object_unref (headers);
6008         }
6009
6010         /* Frees */
6011         g_object_unref (src_folder);
6012 }
6013 #endif
6014
6015 #ifdef MODEST_TOOLKIT_HILDON2
6016 /*
6017  * UI handler for the "Move to" action when invoked from the
6018  * ModestFolderWindow
6019  */
6020 static void
6021 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
6022                                             TnyFolderStore *dst_folder,
6023                                             TnyList *selection,
6024                                             GtkWindow *win)
6025 {
6026         TnyFolderStore *src_folder = NULL;
6027         TnyIterator *iterator;
6028
6029         if (tny_list_get_length (selection) != 1)
6030                 return;
6031
6032         iterator = tny_list_create_iterator (selection);
6033         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
6034         g_object_unref (iterator);
6035
6036
6037         gboolean do_xfer = TRUE;
6038
6039         /* Allow only to transfer folders to the local root folder */
6040         if (TNY_IS_ACCOUNT (dst_folder) &&
6041             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
6042             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
6043                 do_xfer = FALSE;
6044                 /* Show an error */
6045                 modest_platform_run_information_dialog (win,
6046                                                         _("mail_in_ui_folder_move_target_error"),
6047                                                         FALSE);
6048         } else if (!TNY_IS_FOLDER (src_folder)) {
6049                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
6050                 do_xfer = FALSE;
6051         }
6052
6053         if (do_xfer) {
6054                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
6055                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6056
6057                 info->src_folder = g_object_ref (src_folder);
6058                 info->dst_folder = g_object_ref (dst_folder);
6059                 info->delete_original = TRUE;
6060                 info->folder_view = folder_view;
6061
6062                 connect_info->callback = on_move_folder_cb;
6063                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
6064                 connect_info->data = info;
6065
6066                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6067                                                            TNY_FOLDER_STORE (src_folder),
6068                                                            connect_info);
6069         }
6070
6071         /* Frees */
6072         g_object_unref (src_folder);
6073 }
6074 #endif
6075
6076
6077 void
6078 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
6079                                             TnyFolder *src_folder,
6080                                             TnyList *headers,
6081                                             TnyFolder *dst_folder)
6082 {
6083         gboolean need_connection = TRUE;
6084         gboolean do_xfer = TRUE;
6085         XferMsgsHelper *helper;
6086
6087         g_return_if_fail (TNY_IS_FOLDER (src_folder));
6088         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6089         g_return_if_fail (TNY_IS_LIST (headers));
6090
6091         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
6092                                                headers, TNY_FOLDER (dst_folder),
6093                                                TRUE, &need_connection,
6094                                                &do_xfer);
6095
6096         /* If we don't want to transfer just return */
6097         if (!do_xfer)
6098                 return;
6099
6100         /* Create the helper */
6101         helper = g_slice_new (XferMsgsHelper);
6102         helper->dst_folder = g_object_ref (dst_folder);
6103         helper->headers = g_object_ref (headers);
6104
6105         if (need_connection) {
6106                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6107                 connect_info->callback = xfer_messages_performer;
6108                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
6109                 connect_info->data = helper;
6110
6111                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6112                                                            TNY_FOLDER_STORE (src_folder),
6113                                                            connect_info);
6114         } else {
6115                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
6116                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
6117                                          src_account, helper);
6118                 g_object_unref (src_account);
6119         }
6120 }
6121
6122 /*
6123  * UI handler for the "Move to" action when invoked from the
6124  * ModestMsgViewWindow
6125  */
6126 static void
6127 modest_ui_actions_on_window_move_to (GtkAction *action,
6128                                      TnyList *headers,
6129                                      TnyFolderStore *dst_folder,
6130                                      ModestWindow *win)
6131 {
6132         TnyFolder *src_folder = NULL;
6133
6134         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6135
6136         if (headers) {
6137                 TnyHeader *header = NULL;
6138                 TnyIterator *iter;
6139
6140                 iter = tny_list_create_iterator (headers);
6141                 header = (TnyHeader *) tny_iterator_get_current (iter);
6142                 src_folder = tny_header_get_folder (header);
6143
6144                 /* Transfer the messages */
6145                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
6146                                                             headers,
6147                                                             TNY_FOLDER (dst_folder));
6148
6149                 /* Frees */
6150                 g_object_unref (header);
6151                 g_object_unref (iter);
6152                 g_object_unref (src_folder);
6153         }
6154 }
6155
6156 void
6157 modest_ui_actions_on_move_to (GtkAction *action,
6158                               ModestWindow *win)
6159 {
6160         modest_ui_actions_on_edit_mode_move_to (win);
6161 }
6162
6163 gboolean
6164 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
6165 {
6166         GtkWidget *dialog = NULL;
6167         MoveToInfo *helper = NULL;
6168         TnyList *list_to_move;
6169
6170         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
6171
6172 #ifndef MODEST_TOOLKIT_HILDON2
6173         /* Get the main window if exists */
6174         ModestMainWindow *main_window;
6175         if (MODEST_IS_MAIN_WINDOW (win))
6176                 main_window = MODEST_MAIN_WINDOW (win);
6177         else
6178                 main_window =
6179                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
6180                                                                                FALSE)); /* don't create */
6181 #endif
6182
6183         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
6184
6185         if (!list_to_move)
6186                 return FALSE;
6187
6188         if (tny_list_get_length (list_to_move) < 1) {
6189                 g_object_unref (list_to_move);
6190                 return FALSE;
6191         }
6192
6193         /* Create and run the dialog */
6194         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
6195         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
6196                                      GTK_WINDOW (dialog),
6197                                      (GtkWindow *) win);
6198
6199         /* Create helper */
6200         helper = g_slice_new0 (MoveToInfo);
6201         helper->list = list_to_move;
6202         helper->win = win;
6203
6204         /* Listen to response signal */
6205         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
6206
6207         /* Show the dialog */
6208         gtk_widget_show (dialog);
6209
6210         return FALSE;
6211 }
6212
6213 /*
6214  * Calls #HeadersFunc for each header already selected in the main
6215  * window or the message currently being shown in the msg view window
6216  */
6217 static void
6218 do_headers_action (ModestWindow *win,
6219                    HeadersFunc func,
6220                    gpointer user_data)
6221 {
6222         TnyList *headers_list = NULL;
6223         TnyIterator *iter = NULL;
6224         TnyHeader *header = NULL;
6225         TnyFolder *folder = NULL;
6226
6227         /* Get headers */
6228         headers_list = get_selected_headers (win);
6229         if (!headers_list)
6230                 return;
6231
6232         /* Get the folder */
6233         iter = tny_list_create_iterator (headers_list);
6234         header = TNY_HEADER (tny_iterator_get_current (iter));
6235         if (header) {
6236                 folder = tny_header_get_folder (header);
6237                 g_object_unref (header);
6238         }
6239
6240         /* Call the function for each header */
6241         while (!tny_iterator_is_done (iter)) {
6242                 header = TNY_HEADER (tny_iterator_get_current (iter));
6243                 func (header, win, user_data);
6244                 g_object_unref (header);
6245                 tny_iterator_next (iter);
6246         }
6247
6248         /* Trick: do a poke status in order to speed up the signaling
6249            of observers */
6250         if (folder) {
6251                 tny_folder_poke_status (folder);
6252                 g_object_unref (folder);
6253         }
6254
6255         /* Frees */
6256         g_object_unref (iter);
6257         g_object_unref (headers_list);
6258 }
6259
6260 void
6261 modest_ui_actions_view_attachment (GtkAction *action,
6262                                    ModestWindow *window)
6263 {
6264         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6265                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
6266         } else {
6267                 /* not supported window for this action */
6268                 g_return_if_reached ();
6269         }
6270 }
6271
6272 void
6273 modest_ui_actions_save_attachments (GtkAction *action,
6274                                     ModestWindow *window)
6275 {
6276         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6277
6278                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
6279                         return;
6280
6281                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
6282         } else {
6283                 /* not supported window for this action */
6284                 g_return_if_reached ();
6285         }
6286 }
6287
6288 void
6289 modest_ui_actions_remove_attachments (GtkAction *action,
6290                                       ModestWindow *window)
6291 {
6292 #ifndef MODEST_TOOLKIT_HILDON2
6293         if (MODEST_IS_MAIN_WINDOW (window)) {
6294                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
6295         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6296 #else
6297         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6298 #endif
6299                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
6300         } else {
6301                 /* not supported window for this action */
6302                 g_return_if_reached ();
6303         }
6304 }
6305
6306 void
6307 modest_ui_actions_on_settings (GtkAction *action,
6308                                ModestWindow *win)
6309 {
6310         GtkWidget *dialog;
6311
6312         dialog = modest_platform_get_global_settings_dialog ();
6313         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
6314         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
6315         gtk_widget_show_all (dialog);
6316
6317         gtk_dialog_run (GTK_DIALOG (dialog));
6318
6319         gtk_widget_destroy (dialog);
6320 }
6321
6322 void
6323 modest_ui_actions_on_help (GtkAction *action,
6324                            GtkWindow *win)
6325 {
6326         /* Help app is not available at all in fremantle */
6327 #ifndef MODEST_TOOLKIT_HILDON2
6328         const gchar *help_id;
6329
6330         g_return_if_fail (win && GTK_IS_WINDOW(win));
6331
6332         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
6333
6334         if (help_id)
6335                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6336 #endif
6337 }
6338
6339 void
6340 modest_ui_actions_on_csm_help (GtkAction *action,
6341                                GtkWindow *win)
6342 {
6343         /* Help app is not available at all in fremantle */
6344 #ifndef MODEST_TOOLKIT_HILDON2
6345
6346         const gchar* help_id = NULL;
6347         GtkWidget *folder_view;
6348         TnyFolderStore *folder_store;
6349
6350         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
6351
6352         /* Get selected folder */
6353         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
6354                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6355         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6356
6357         /* Switch help_id */
6358         if (folder_store && TNY_IS_FOLDER (folder_store))
6359                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
6360
6361         if (folder_store)
6362                 g_object_unref (folder_store);
6363
6364         if (help_id)
6365                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6366         else
6367                 modest_ui_actions_on_help (action, win);
6368 #endif
6369 }
6370
6371 static void
6372 retrieve_contents_cb (ModestMailOperation *mail_op,
6373                       TnyHeader *header,
6374                       gboolean canceled,
6375                       TnyMsg *msg,
6376                       GError *err,
6377                       gpointer user_data)
6378 {
6379         /* We only need this callback to show an error in case of
6380            memory low condition */
6381         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
6382                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
6383         }
6384 }
6385
6386 static void
6387 retrieve_msg_contents_performer (gboolean canceled,
6388                                  GError *err,
6389                                  GtkWindow *parent_window,
6390                                  TnyAccount *account,
6391                                  gpointer user_data)
6392 {
6393         ModestMailOperation *mail_op;
6394         TnyList *headers = TNY_LIST (user_data);
6395
6396         if (err || canceled) {
6397                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
6398                                                                 (GtkWidget *) parent_window, err,
6399                                                                 account, NULL);
6400                 goto out;
6401         }
6402
6403         /* Create mail operation */
6404         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
6405                                                                  modest_ui_actions_disk_operations_error_handler,
6406                                                                  NULL, NULL);
6407         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
6408         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
6409
6410         /* Frees */
6411         g_object_unref (mail_op);
6412  out:
6413         g_object_unref (headers);
6414         g_object_unref (account);
6415 }
6416
6417 void
6418 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
6419                                             ModestWindow *window)
6420 {
6421         TnyList *headers = NULL;
6422         TnyAccount *account = NULL;
6423         TnyIterator *iter = NULL;
6424         TnyHeader *header = NULL;
6425         TnyFolder *folder = NULL;
6426
6427         /* Get headers */
6428         headers = get_selected_headers (window);
6429         if (!headers)
6430                 return;
6431
6432         /* Pick the account */
6433         iter = tny_list_create_iterator (headers);
6434         header = TNY_HEADER (tny_iterator_get_current (iter));
6435         folder = tny_header_get_folder (header);
6436         account = tny_folder_get_account (folder);
6437         g_object_unref (folder);
6438         g_object_unref (header);
6439         g_object_unref (iter);
6440
6441         /* Connect and perform the message retrieval */
6442         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
6443                                              g_object_ref (account),
6444                                              retrieve_msg_contents_performer,
6445                                              g_object_ref (headers));
6446
6447         /* Frees */
6448         g_object_unref (account);
6449         g_object_unref (headers);
6450 }
6451
6452 void
6453 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
6454 {
6455         g_return_if_fail (MODEST_IS_WINDOW (window));
6456
6457         /* Update dimmed */
6458         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
6459 }
6460
6461 void
6462 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
6463 {
6464         g_return_if_fail (MODEST_IS_WINDOW (window));
6465
6466         /* Update dimmed */
6467         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
6468 }
6469
6470 void
6471 modest_ui_actions_on_email_menu_activated (GtkAction *action,
6472                                           ModestWindow *window)
6473 {
6474         g_return_if_fail (MODEST_IS_WINDOW (window));
6475
6476         /* Update dimmed */
6477         modest_ui_actions_check_menu_dimming_rules (window);
6478 }
6479
6480 void
6481 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
6482                                           ModestWindow *window)
6483 {
6484         g_return_if_fail (MODEST_IS_WINDOW (window));
6485
6486         /* Update dimmed */
6487         modest_ui_actions_check_menu_dimming_rules (window);
6488 }
6489
6490 void
6491 modest_ui_actions_on_view_menu_activated (GtkAction *action,
6492                                           ModestWindow *window)
6493 {
6494         g_return_if_fail (MODEST_IS_WINDOW (window));
6495
6496         /* Update dimmed */
6497         modest_ui_actions_check_menu_dimming_rules (window);
6498 }
6499
6500 void
6501 modest_ui_actions_on_format_menu_activated (GtkAction *action,
6502                                             ModestWindow *window)
6503 {
6504         g_return_if_fail (MODEST_IS_WINDOW (window));
6505
6506         /* Update dimmed */
6507         modest_ui_actions_check_menu_dimming_rules (window);
6508 }
6509
6510 void
6511 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
6512                                           ModestWindow *window)
6513 {
6514         g_return_if_fail (MODEST_IS_WINDOW (window));
6515
6516         /* Update dimmed */
6517         modest_ui_actions_check_menu_dimming_rules (window);
6518 }
6519
6520 void
6521 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
6522                                           ModestWindow *window)
6523 {
6524         g_return_if_fail (MODEST_IS_WINDOW (window));
6525
6526         /* Update dimmed */
6527         modest_ui_actions_check_menu_dimming_rules (window);
6528 }
6529
6530 void
6531 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
6532                                                  ModestWindow *window)
6533 {
6534         g_return_if_fail (MODEST_IS_WINDOW (window));
6535
6536         /* Update dimmed */
6537         modest_ui_actions_check_menu_dimming_rules (window);
6538 }
6539
6540 void
6541 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
6542                                                      ModestWindow *window)
6543 {
6544         g_return_if_fail (MODEST_IS_WINDOW (window));
6545
6546         /* Update dimmed */
6547         modest_ui_actions_check_menu_dimming_rules (window);
6548 }
6549
6550 void
6551 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
6552                                                      ModestWindow *window)
6553 {
6554         g_return_if_fail (MODEST_IS_WINDOW (window));
6555
6556         /* Update dimmed */
6557         modest_ui_actions_check_menu_dimming_rules (window);
6558 }
6559
6560 void
6561 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6562 {
6563         g_return_if_fail (MODEST_IS_WINDOW (window));
6564
6565         /* we check for low-mem; in that case, show a warning, and don't allow
6566          * searching
6567          */
6568         if (modest_platform_check_memory_low (window, TRUE))
6569                 return;
6570
6571         modest_platform_show_search_messages (GTK_WINDOW (window));
6572 }
6573
6574 void
6575 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6576 {
6577         g_return_if_fail (MODEST_IS_WINDOW (win));
6578
6579
6580         /* we check for low-mem; in that case, show a warning, and don't allow
6581          * for the addressbook
6582          */
6583         if (modest_platform_check_memory_low (win, TRUE))
6584                 return;
6585
6586
6587         modest_platform_show_addressbook (GTK_WINDOW (win));
6588 }
6589
6590
6591 void
6592 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
6593                                           ModestWindow *window)
6594 {
6595         gboolean active;
6596         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6597
6598         if (GTK_IS_TOGGLE_ACTION (action))
6599                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
6600         else
6601                 active = TRUE;
6602
6603         modest_msg_edit_window_toggle_isearch_toolbar (MODEST_MSG_EDIT_WINDOW (window),
6604                                                        active);
6605 }
6606
6607 #ifndef MODEST_TOOLKIT_HILDON2
6608 static void
6609 on_send_receive_finished (ModestMailOperation  *mail_op,
6610                            gpointer user_data)
6611 {
6612         GtkWidget *header_view, *folder_view;
6613         TnyFolderStore *folder_store;
6614         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6615
6616         /* Set send/receive operation finished */
6617         modest_main_window_notify_send_receive_completed (main_win);
6618
6619         /* Don't refresh the current folder if there were any errors */
6620         if (modest_mail_operation_get_status (mail_op) !=
6621             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6622                 return;
6623
6624         /* Refresh the current folder if we're viewing a window. We do
6625            this because the user won't be able to see the new mails in
6626            the selected folder after a Send&Receive because it only
6627            performs a poke_status, i.e, only the number of read/unread
6628            messages is updated, but the new headers are not
6629            downloaded */
6630         folder_view = modest_main_window_get_child_widget (main_win,
6631                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6632         if (!folder_view)
6633                 return;
6634
6635         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6636
6637         /* Do not need to refresh INBOX again because the
6638            update_account does it always automatically */
6639         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6640             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6641                 ModestMailOperation *refresh_op;
6642
6643                 header_view = modest_main_window_get_child_widget (main_win,
6644                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6645
6646                 /* We do not need to set the contents style
6647                    because it hasn't changed. We also do not
6648                    need to save the widget status. Just force
6649                    a refresh */
6650                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6651                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6652                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6653                                                       folder_refreshed_cb, main_win);
6654                 g_object_unref (refresh_op);
6655         }
6656
6657         if (folder_store)
6658                 g_object_unref (folder_store);
6659 }
6660 #endif
6661
6662 void
6663 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6664                                                 TnyHeader *header,
6665                                                 TnyMsg *msg,
6666                                                 GError *err,
6667                                                 gpointer user_data)
6668 {
6669         const gchar* server_name = NULL;
6670         TnyTransportAccount *transport;
6671         gchar *message = NULL;
6672         ModestProtocol *protocol;
6673
6674         /* Don't show anything if the user cancelled something or the
6675          * send receive request is not interactive. Authentication
6676          * errors are managed by the account store so no need to show
6677          * a dialog here again */
6678         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6679             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6680             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6681                 return;
6682
6683
6684         /* Get the server name. Note that we could be using a
6685            connection specific transport account */
6686         transport = (TnyTransportAccount *)
6687                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
6688         if (transport) {
6689                 ModestTnyAccountStore *acc_store;
6690                 const gchar *acc_name;
6691                 TnyTransportAccount *conn_specific;
6692
6693                 acc_store = modest_runtime_get_account_store();
6694                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
6695                 conn_specific = (TnyTransportAccount *)
6696                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
6697                 if (conn_specific) {
6698                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
6699                         g_object_unref (conn_specific);
6700                 } else {
6701                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
6702                 }
6703                 g_object_unref (transport);
6704         }
6705
6706         /* Get protocol */
6707         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
6708                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
6709                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
6710         if (!protocol) {
6711                 g_warning ("%s: Account with no proto", __FUNCTION__);
6712                 return;
6713         }
6714
6715         /* Show the appropriate message text for the GError: */
6716         switch (err->code) {
6717         case TNY_SERVICE_ERROR_CONNECT:
6718                 message = modest_protocol_get_translation (protocol,
6719                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
6720                                                            server_name);
6721                 break;
6722         case TNY_SERVICE_ERROR_SEND:
6723                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6724                 break;
6725         case TNY_SERVICE_ERROR_UNAVAILABLE:
6726                 message = modest_protocol_get_translation (protocol,
6727                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
6728                                                            server_name);
6729                 break;
6730         default:
6731                 g_warning ("%s: unexpected ERROR %d",
6732                            __FUNCTION__, err->code);
6733                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6734                 break;
6735         }
6736
6737         modest_platform_run_information_dialog (NULL, message, FALSE);
6738         g_free (message);
6739 }
6740
6741 void
6742 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6743                                                 gchar *msg_id,
6744                                                 guint status,
6745                                                 gpointer user_data)
6746 {
6747         ModestWindow *top_window = NULL;
6748         ModestWindowMgr *mgr = NULL;
6749         GtkWidget *header_view = NULL;
6750         TnyFolder *selected_folder = NULL;
6751         TnyFolderType folder_type;
6752
6753         mgr = modest_runtime_get_window_mgr ();
6754         top_window = modest_window_mgr_get_current_top (mgr);
6755
6756         if (!top_window)
6757                 return;
6758
6759 #ifndef MODEST_TOOLKIT_HILDON2
6760         if (MODEST_IS_MAIN_WINDOW (top_window)) {
6761                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (top_window),
6762                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6763         }
6764 #else
6765         if (MODEST_IS_HEADER_WINDOW (top_window)) {
6766                 header_view = (GtkWidget *)
6767                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
6768         }
6769 #endif
6770
6771         /* Get selected folder */
6772         if (header_view)
6773                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
6774         if (!selected_folder)
6775                 return;
6776
6777         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6778 #if GTK_CHECK_VERSION(2, 8, 0)
6779         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
6780         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
6781                 GtkTreeViewColumn *tree_column;
6782
6783                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
6784                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6785                 if (tree_column)
6786                         gtk_tree_view_column_queue_resize (tree_column);
6787                 }
6788 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
6789         gtk_widget_queue_draw (header_view);
6790 #endif
6791
6792 #ifndef MODEST_TOOLKIT_HILDON2
6793         /* Rerun dimming rules, because the message could become deletable for example */
6794         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6795                                                  MODEST_DIMMING_RULES_TOOLBAR);
6796         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6797                                                  MODEST_DIMMING_RULES_MENU);
6798 #endif
6799
6800         /* Free */
6801         g_object_unref (selected_folder);
6802 }
6803
6804 void
6805 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6806                                                TnyAccount *account)
6807 {
6808         ModestProtocolType protocol_type;
6809         ModestProtocol *protocol;
6810         gchar *error_note = NULL;
6811
6812         protocol_type = modest_tny_account_get_protocol_type (account);
6813         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6814                                                                   protocol_type);
6815
6816         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6817         if (error_note == NULL) {
6818                 g_warning ("%s: This should not be reached", __FUNCTION__);
6819         } else {
6820                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6821                 g_free (error_note);
6822         }
6823 }
6824
6825 gchar *
6826 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6827 {
6828         gchar *msg = NULL;
6829         gchar *subject;
6830         TnyFolderStore *folder = NULL;
6831         TnyAccount *account = NULL;
6832         ModestProtocolType proto;
6833         ModestProtocol *protocol;
6834         TnyHeader *header = NULL;
6835
6836 #ifndef MODEST_TOOLKIT_HILDON2
6837         if (MODEST_IS_MAIN_WINDOW (win)) {
6838                 GtkWidget *header_view;
6839                 TnyList* headers = NULL;
6840                 TnyIterator *iter;
6841                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6842                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6843                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6844                 if (!headers || tny_list_get_length (headers) == 0) {
6845                         if (headers)
6846                                 g_object_unref (headers);
6847                         return NULL;
6848                 }
6849                 iter = tny_list_create_iterator (headers);
6850                 header = TNY_HEADER (tny_iterator_get_current (iter));
6851                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6852                 g_object_unref (iter);
6853                 g_object_unref (headers);
6854 #else
6855         if (MODEST_IS_HEADER_WINDOW (win)) {
6856                 GtkWidget *header_view;
6857                 TnyList* headers = NULL;
6858                 TnyIterator *iter;
6859                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
6860                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6861                 if (!headers || tny_list_get_length (headers) == 0) {
6862                         if (headers)
6863                                 g_object_unref (headers);
6864                         return NULL;
6865                 }
6866                 iter = tny_list_create_iterator (headers);
6867                 header = TNY_HEADER (tny_iterator_get_current (iter));
6868                 if (header) {
6869                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6870                 } else {
6871                         g_warning ("List should contain headers");
6872                 }
6873                 g_object_unref (iter);
6874                 g_object_unref (headers);
6875 #endif
6876         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6877                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6878                 if (header)
6879                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6880         }
6881
6882         if (!header || !folder)
6883                 goto frees;
6884
6885         /* Get the account type */
6886         account = tny_folder_get_account (TNY_FOLDER (folder));
6887         proto = modest_tny_account_get_protocol_type (account);
6888         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6889                                                                   proto);
6890
6891         subject = tny_header_dup_subject (header);
6892         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6893         if (subject)
6894                 g_free (subject);
6895         if (msg == NULL) {
6896                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6897         }
6898
6899  frees:
6900         /* Frees */
6901         if (account)
6902                 g_object_unref (account);
6903         if (folder)
6904                 g_object_unref (folder);
6905         if (header)
6906                 g_object_unref (header);
6907
6908         return msg;
6909 }
6910
6911 gboolean
6912 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6913                                      const gchar *account_name,
6914                                      const gchar *account_title)
6915 {
6916         ModestAccountMgr *account_mgr;
6917         gchar *txt = NULL;
6918         gint response;
6919         ModestProtocol *protocol;
6920         gboolean removed = FALSE;
6921
6922         g_return_val_if_fail (account_name, FALSE);
6923         g_return_val_if_fail (account_title, FALSE);
6924
6925         account_mgr = modest_runtime_get_account_mgr();
6926
6927         /* The warning text depends on the account type: */
6928         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6929                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6930                                                                                                          account_name));
6931         txt = modest_protocol_get_translation (protocol,
6932                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6933                                                account_title);
6934         if (txt == NULL)
6935                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6936
6937         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6938         g_free (txt);
6939         txt = NULL;
6940
6941         if (response == GTK_RESPONSE_OK) {
6942                 /* Remove account. If it succeeds then it also removes
6943                    the account from the ModestAccountView: */
6944                 gboolean is_default = FALSE;
6945                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6946                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6947                         is_default = TRUE;
6948                 g_free (default_account_name);
6949
6950                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6951                 if (removed) {
6952                         /* Close all email notifications, we cannot
6953                            distinguish if the notification belongs to
6954                            this account or not, so for safety reasons
6955                            we remove them all */
6956                         modest_platform_remove_new_mail_notifications (FALSE);
6957                 } else {
6958                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6959                 }
6960         }
6961         return removed;
6962 }
6963
6964 static void
6965 on_fetch_images_performer (gboolean canceled,
6966                            GError *err,
6967                            GtkWindow *parent_window,
6968                            TnyAccount *account,
6969                            gpointer user_data)
6970 {
6971         if (err || canceled) {
6972                 /* Show an unable to retrieve images ??? */
6973                 return;
6974         }
6975
6976         /* Note that the user could have closed the window while connecting */
6977         if (GTK_WIDGET_VISIBLE (parent_window))
6978                 modest_msg_view_window_fetch_images ((ModestMsgViewWindow *) parent_window);
6979         g_object_unref ((GObject *) user_data);
6980 }
6981
6982 void
6983 modest_ui_actions_on_fetch_images (GtkAction *action,
6984                                    ModestWindow *window)
6985 {
6986         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
6987
6988         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE, 
6989                                              NULL,
6990                                              on_fetch_images_performer, 
6991                                              g_object_ref (window));
6992 }
6993
6994 void
6995 modest_ui_actions_on_reload_message (const gchar *msg_id)
6996 {
6997         ModestWindow *window = NULL;
6998
6999         g_return_if_fail (msg_id && msg_id[0] != '\0');
7000         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
7001                                                             msg_id,
7002                                                             &window))
7003                 return;
7004
7005
7006         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
7007                 return;
7008
7009         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
7010 }
7011
7012 /** Check whether any connections are active, and cancel them if 
7013  * the user wishes.
7014  * Returns TRUE is there was no problem, 
7015  * or if an operation was cancelled so we can continue.
7016  * Returns FALSE if the user chose to cancel his request instead.
7017  */
7018
7019 gboolean
7020 modest_ui_actions_check_for_active_account (ModestWindow *self,
7021                                             const gchar* account_name)
7022 {
7023         ModestTnySendQueue *send_queue;
7024         ModestTnyAccountStore *acc_store;
7025         ModestMailOperationQueue* queue;
7026         TnyConnectionStatus store_conn_status;
7027         TnyAccount *store_account = NULL, *transport_account = NULL;
7028         gboolean retval = TRUE, sending = FALSE;
7029
7030         acc_store = modest_runtime_get_account_store ();
7031         queue = modest_runtime_get_mail_operation_queue ();
7032
7033         store_account = 
7034                 modest_tny_account_store_get_server_account (acc_store,
7035                                                              account_name,
7036                                                              TNY_ACCOUNT_TYPE_STORE);
7037
7038         /* This could happen if the account was deleted before the
7039            call to this function */
7040         if (!store_account)
7041                 return FALSE;
7042
7043         transport_account = 
7044                 modest_tny_account_store_get_server_account (acc_store,
7045                                                              account_name,
7046                                                              TNY_ACCOUNT_TYPE_TRANSPORT);
7047
7048         /* This could happen if the account was deleted before the
7049            call to this function */
7050         if (!transport_account) {
7051                 g_object_unref (store_account);
7052                 return FALSE;
7053         }
7054
7055         /* If the transport account was not used yet, then the send
7056            queue could not exist (it's created on demand) */
7057         send_queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (transport_account), FALSE);
7058         if (TNY_IS_SEND_QUEUE (send_queue))
7059                 sending = modest_tny_send_queue_sending_in_progress (send_queue);
7060
7061         store_conn_status = tny_account_get_connection_status (store_account);
7062         if (store_conn_status == TNY_CONNECTION_STATUS_CONNECTED || sending) {
7063                 gint response;
7064
7065                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (self), 
7066                                                                 _("emev_nc_disconnect_account"));
7067                 if (response == GTK_RESPONSE_OK) {
7068                         retval = TRUE;
7069                 } else {
7070                         retval = FALSE;
7071                 }
7072         }
7073
7074         if (retval) {
7075
7076                 /* FIXME: We should only cancel those of this account */
7077                 modest_mail_operation_queue_cancel_all (queue);
7078
7079                 /* Also disconnect the account */
7080                 if ((tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED) &&
7081                     (tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED_BROKEN)) {
7082                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account),
7083                                                       FALSE, NULL, NULL);
7084                 }
7085                 if (sending) {
7086                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (transport_account),
7087                                                       FALSE, NULL, NULL);
7088                 }
7089         }
7090                 
7091         /* Frees */
7092         g_object_unref (store_account);
7093         g_object_unref (transport_account);
7094         
7095         return retval;
7096 }