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