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