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