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