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