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