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