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