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