Fixes NB#139637, coverity defects in modest
[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 && gtk_tree_row_reference_valid (rowref));
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 gboolean
2155 idle_refresh_folder (gpointer source)
2156 {
2157         ModestHeaderView *header_view = NULL;
2158
2159         /* If the window still exists */
2160         if (!GTK_IS_WIDGET (source) ||
2161             !GTK_WIDGET_VISIBLE (source))
2162                 return FALSE;
2163
2164         /* Refresh the current view */
2165 #ifdef MODEST_TOOLKIT_HILDON2
2166         if (MODEST_IS_HEADER_WINDOW (source))
2167                 header_view = modest_header_window_get_header_view ((ModestHeaderWindow *) source);
2168 #else
2169         if (MODEST_IS_MAIN_WINDOW (source))
2170                 header_view = modest_main_window_get_child_widget ((ModestMainWindow *) source,
2171                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2172 #endif
2173         if (header_view) {
2174                 TnyFolder *folder = modest_header_view_get_folder (header_view);
2175                 if (folder) {
2176                         /* We must clear first, because otherwise set_folder will ignore
2177                            the change as the folders are the same */
2178                         modest_header_view_clear (header_view);
2179                         modest_header_view_set_folder (header_view, folder, TRUE,
2180                                                        (ModestWindow *) source, NULL, NULL);
2181                         g_object_unref (folder);
2182                 }
2183         }
2184
2185         return FALSE;
2186 }
2187
2188 static void
2189 update_account_cb (ModestMailOperation *self,
2190                    TnyList *new_headers,
2191                    gpointer user_data)
2192 {
2193         GObject *source;
2194         gboolean show_visual_notifications;
2195
2196         source = modest_mail_operation_get_source (self);
2197         show_visual_notifications = (source) ? FALSE : TRUE;
2198
2199         /* Notify new messages have been downloaded. If the
2200            send&receive was invoked by the user then do not show any
2201            visual notification, only play a sound and activate the LED
2202            (for the Maemo version) */
2203         if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0) {
2204
2205                 /* We only notify about really new messages (not seen) we get */
2206                 TnyList *actually_new_list;
2207                 TnyIterator *iterator;
2208                 actually_new_list = TNY_LIST (tny_simple_list_new ());
2209                 for (iterator = tny_list_create_iterator (new_headers);
2210                      !tny_iterator_is_done (iterator);
2211                      tny_iterator_next (iterator)) {
2212                         TnyHeader *header;
2213                         TnyHeaderFlags flags;
2214                         header = TNY_HEADER (tny_iterator_get_current (iterator));
2215                         flags = tny_header_get_flags (header);
2216
2217                         if (!(flags & TNY_HEADER_FLAG_SEEN)) {
2218                                 /* Messages are ordered from most
2219                                    recent to oldest. But we want to
2220                                    show notifications starting from
2221                                    the oldest message. That's why we
2222                                    reverse the list */
2223                                 tny_list_prepend (actually_new_list, G_OBJECT (header));
2224                         }
2225                         g_object_unref (header);
2226                 }
2227                 g_object_unref (iterator);
2228
2229                 if (tny_list_get_length (actually_new_list) > 0) {
2230                         GList *new_headers_list = NULL;
2231
2232                         new_headers_list = modest_utils_create_notification_list_from_header_list (actually_new_list);
2233
2234                         /* Send notifications */
2235                         if (new_headers_list) {
2236                                 modest_platform_on_new_headers_received (new_headers_list,
2237                                                                          show_visual_notifications);
2238                                 /* Free the list */
2239                                 modest_utils_free_notification_list (new_headers_list);
2240                         }
2241                 }
2242                 g_object_unref (actually_new_list);
2243         }
2244
2245         if (source) {
2246                 /* Refresh the current folder in an idle. We do this
2247                    in order to avoid refresh cancelations if the
2248                    currently viewed folder is the inbox */
2249                 g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
2250                                  idle_refresh_folder,
2251                                  g_object_ref (source),
2252                                  g_object_unref);
2253                 g_object_unref (source);
2254         }
2255 }
2256
2257 typedef struct {
2258         TnyAccount *account;
2259         ModestWindow *win;
2260         gchar *account_name;
2261         gboolean poke_status;
2262         gboolean interactive;
2263         ModestMailOperation *mail_op;
2264 } SendReceiveInfo;
2265
2266 static void
2267 do_send_receive_performer (gboolean canceled,
2268                            GError *err,
2269                            GtkWindow *parent_window,
2270                            TnyAccount *account,
2271                            gpointer user_data)
2272 {
2273         SendReceiveInfo *info;
2274
2275         info = (SendReceiveInfo *) user_data;
2276
2277         if (err || canceled) {
2278                 /* In disk full conditions we could get this error here */
2279                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
2280                                                                 (GtkWidget *) parent_window, err,
2281                                                                 account, NULL);
2282
2283                 if (info->mail_op) {
2284                         modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
2285                                                             info->mail_op);
2286                 }
2287                 goto clean;
2288         }
2289
2290         /* Set send/receive operation in progress */
2291         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
2292                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
2293         }
2294
2295         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
2296                 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
2297                                   G_CALLBACK (on_send_receive_finished),
2298                                   info->win);
2299
2300         /* Send & receive. */
2301         modest_mail_operation_update_account (info->mail_op, info->account_name, info->poke_status, info->interactive,
2302                                               update_account_cb, info->win);
2303
2304  clean:
2305         /* Frees */
2306         if (info->mail_op)
2307                 g_object_unref (G_OBJECT (info->mail_op));
2308         if (info->account_name)
2309                 g_free (info->account_name);
2310         if (info->win)
2311                 g_object_unref (info->win);
2312         if (info->account)
2313                 g_object_unref (info->account);
2314         g_slice_free (SendReceiveInfo, info);
2315 }
2316
2317 /*
2318  * This function performs the send & receive required actions. The
2319  * window is used to create the mail operation. Typically it should
2320  * always be the main window, but we pass it as argument in order to
2321  * be more flexible.
2322  */
2323 void
2324 modest_ui_actions_do_send_receive (const gchar *account_name,
2325                                    gboolean force_connection,
2326                                    gboolean poke_status,
2327                                    gboolean interactive,
2328                                    ModestWindow *win)
2329 {
2330         gchar *acc_name = NULL;
2331         SendReceiveInfo *info;
2332         ModestTnyAccountStore *acc_store;
2333         TnyAccount *account;
2334
2335         /* If no account name was provided then get the current account, and if
2336            there is no current account then pick the default one: */
2337         if (!account_name) {
2338                 if (win)
2339                         acc_name = g_strdup (modest_window_get_active_account (win));
2340                 if (!acc_name)
2341                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
2342                 if (!acc_name) {
2343                         modest_platform_information_banner (NULL, NULL, _("emev_ni_internal_error"));
2344                         return;
2345                 }
2346         } else {
2347                 acc_name = g_strdup (account_name);
2348         }
2349
2350         acc_store = modest_runtime_get_account_store ();
2351         account = modest_tny_account_store_get_server_account (acc_store, acc_name, TNY_ACCOUNT_TYPE_STORE);
2352
2353         if (!account) {
2354                 g_free (acc_name);
2355                 modest_platform_information_banner (NULL, NULL, _("emev_ni_internal_error"));
2356                 return;
2357         }
2358
2359         /* Do not automatically refresh accounts that are flagged as
2360            NO_AUTO_UPDATE. This could be useful for accounts that
2361            handle their own update times */
2362         if (!interactive) {
2363                 ModestProtocolType proto = modest_tny_account_get_protocol_type (account);
2364                 if (proto != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
2365                         const gchar *tag = MODEST_PROTOCOL_REGISTRY_NO_AUTO_UPDATE_PROTOCOLS;
2366                         ModestProtocolRegistry *registry = modest_runtime_get_protocol_registry ();
2367
2368                         if (modest_protocol_registry_protocol_type_has_tag (registry, proto, tag)) {
2369                                 g_debug ("%s no auto update allowed for account %s", __FUNCTION__, account_name);
2370                                 g_object_unref (account);
2371                                 g_free (acc_name);
2372                                 return;
2373                         }
2374                 }
2375         }
2376
2377         /* Create the info for the connect and perform */
2378         info = g_slice_new (SendReceiveInfo);
2379         info->account_name = acc_name;
2380         info->win = (win) ? g_object_ref (win) : NULL;
2381         info->poke_status = poke_status;
2382         info->interactive = interactive;
2383         info->account = account;
2384         /* We need to create the operation here, because otherwise it
2385            could happen that the queue emits the queue-empty signal
2386            while we're trying to connect the account */
2387         info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
2388                                                                        modest_ui_actions_disk_operations_error_handler,
2389                                                                        NULL, NULL);
2390         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
2391
2392         /* Invoke the connect and perform */
2393         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
2394                                              force_connection, info->account,
2395                                              do_send_receive_performer, info);
2396 }
2397
2398
2399 static void
2400 modest_ui_actions_do_cancel_send (const gchar *account_name,
2401                                   ModestWindow *win)
2402 {
2403         TnyTransportAccount *transport_account;
2404         TnySendQueue *send_queue = NULL;
2405         GError *error = NULL;
2406
2407         /* Get transport account */
2408         transport_account =
2409                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2410                                       (modest_runtime_get_account_store(),
2411                                        account_name,
2412                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2413         if (!transport_account) {
2414                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2415                 goto frees;
2416         }
2417
2418         /* Get send queue*/
2419         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2420         if (!TNY_IS_SEND_QUEUE(send_queue)) {
2421                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2422                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2423                              "modest: could not find send queue for account\n");
2424         } else {
2425                 /* Cancel the current send */
2426                 tny_account_cancel (TNY_ACCOUNT (transport_account));
2427
2428                 /* Suspend all pending messages */
2429                 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2430         }
2431
2432  frees:
2433         if (transport_account != NULL)
2434                 g_object_unref (G_OBJECT (transport_account));
2435 }
2436
2437 static void
2438 modest_ui_actions_cancel_send_all (ModestWindow *win)
2439 {
2440         GSList *account_names, *iter;
2441
2442         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2443                                                           TRUE);
2444
2445         iter = account_names;
2446         while (iter) {
2447                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2448                 iter = g_slist_next (iter);
2449         }
2450
2451         modest_account_mgr_free_account_names (account_names);
2452         account_names = NULL;
2453 }
2454
2455 void
2456 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
2457
2458 {
2459         /* Check if accounts exist */
2460         gboolean accounts_exist =
2461                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2462
2463         /* If not, allow the user to create an account before trying to send/receive. */
2464         if (!accounts_exist)
2465                 modest_ui_actions_on_accounts (NULL, win);
2466
2467         /* Cancel all sending operaitons */
2468         modest_ui_actions_cancel_send_all (win);
2469 }
2470
2471 /*
2472  * Refreshes all accounts. This function will be used by automatic
2473  * updates
2474  */
2475 void
2476 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2477                                        gboolean force_connection,
2478                                        gboolean poke_status,
2479                                        gboolean interactive)
2480 {
2481         GSList *account_names, *iter;
2482
2483         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2484                                                           TRUE);
2485
2486         iter = account_names;
2487         while (iter) {
2488                 modest_ui_actions_do_send_receive ((const char*) iter->data,
2489                                                    force_connection,
2490                                                    poke_status, interactive, win);
2491                 iter = g_slist_next (iter);
2492         }
2493
2494         modest_account_mgr_free_account_names (account_names);
2495         account_names = NULL;
2496 }
2497
2498 /*
2499  * Handler of the click on Send&Receive button in the main toolbar
2500  */
2501 void
2502 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2503 {
2504         /* Check if accounts exist */
2505         gboolean accounts_exist;
2506
2507         accounts_exist =
2508                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2509
2510         /* If not, allow the user to create an account before trying to send/receive. */
2511         if (!accounts_exist)
2512                 modest_ui_actions_on_accounts (NULL, win);
2513
2514         /* Refresh the current folder. The if is always TRUE it's just an extra check */
2515         if (MODEST_IS_MAIN_WINDOW (win)) {
2516                 GtkWidget *folder_view;
2517                 TnyFolderStore *folder_store;
2518
2519                 folder_view =
2520                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2521                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2522                 if (!folder_view)
2523                         return;
2524
2525                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2526
2527                 if (folder_store)
2528                         g_object_unref (folder_store);
2529                 /* Refresh the active account. Force the connection if needed
2530                    and poke the status of all folders */
2531                 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2532 #ifdef MODEST_TOOLKIT_HILDON2
2533         } else if (MODEST_IS_ACCOUNTS_WINDOW (win)) {
2534                 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2535 #endif
2536         } else {
2537                 const gchar *active_account;
2538                 active_account = modest_window_get_active_account (MODEST_WINDOW (win));
2539
2540                 modest_ui_actions_do_send_receive (active_account, TRUE, TRUE, TRUE, win);
2541         }
2542
2543 }
2544
2545
2546 void
2547 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2548 {
2549         ModestConf *conf;
2550         GtkWidget *header_view;
2551
2552         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2553
2554         header_view = modest_main_window_get_child_widget (main_window,
2555                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2556         if (!header_view)
2557                 return;
2558
2559         conf = modest_runtime_get_conf ();
2560
2561         /* what is saved/restored is depending on the style; thus; we save with
2562          * old style, then update the style, and restore for this new style
2563          */
2564         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2565
2566         if (modest_header_view_get_style
2567             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2568                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2569                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
2570         else
2571                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2572                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
2573
2574         modest_widget_memory_restore (conf, G_OBJECT(header_view),
2575                                       MODEST_CONF_HEADER_VIEW_KEY);
2576 }
2577
2578
2579 void
2580 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2581                                       TnyHeader *header,
2582                                       ModestMainWindow *main_window)
2583 {
2584         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2585         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2586
2587         /* in the case the folder is empty, show the empty folder message and focus
2588          * folder view */
2589         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2590                 if (modest_header_view_is_empty (header_view)) {
2591                         TnyFolder *folder = modest_header_view_get_folder (header_view);
2592                         GtkWidget *folder_view =
2593                                 modest_main_window_get_child_widget (main_window,
2594                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2595                         if (folder != NULL) {
2596                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2597                                 g_object_unref (folder);
2598                         }
2599                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2600                         return;
2601                 }
2602         }
2603         /* If no header has been selected then exit */
2604         if (!header)
2605                 return;
2606
2607         /* Update focus */
2608         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2609             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2610
2611         /* Update toolbar dimming state */
2612         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2613         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2614 }
2615
2616 void
2617 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2618                                        TnyHeader *header,
2619                                        GtkTreePath *path,
2620                                        ModestWindow *window)
2621 {
2622         GtkWidget *open_widget;
2623         GtkTreeRowReference *rowref;
2624
2625         g_return_if_fail (MODEST_IS_WINDOW(window));
2626         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2627         g_return_if_fail (TNY_IS_HEADER (header));
2628
2629         if (modest_header_view_count_selected_headers (header_view) > 1) {
2630                 /* Don't allow activation if there are more than one message selected */
2631                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2632                 return;
2633         }
2634
2635         /* we check for low-mem; in that case, show a warning, and don't allow
2636          * activating headers
2637          */
2638         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2639                 return;
2640
2641         if (MODEST_IS_MAIN_WINDOW (window)) {
2642                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2643                 open_widget = modest_window_get_action_widget (MODEST_WINDOW (window), "/MenuBar/EmailMenu/EmailOpenMenu");
2644                 if (!GTK_WIDGET_IS_SENSITIVE (open_widget))
2645                         return;
2646         }
2647
2648         rowref = gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)), path);
2649         open_msg_from_header (header, rowref, MODEST_WINDOW (window));
2650         gtk_tree_row_reference_free (rowref);
2651 }
2652
2653 static void
2654 set_active_account_from_tny_account (TnyAccount *account,
2655                                      ModestWindow *window)
2656 {
2657         const gchar *server_acc_name = tny_account_get_id (account);
2658
2659         /* We need the TnyAccount provided by the
2660            account store because that is the one that
2661            knows the name of the Modest account */
2662         TnyAccount *modest_server_account =
2663                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2664                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2665                                                              server_acc_name);
2666         if (!modest_server_account) {
2667                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2668                 return;
2669         }
2670
2671         /* Update active account, but only if it's not a pseudo-account */
2672         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2673             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2674                 const gchar *modest_acc_name =
2675                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2676                 if (modest_acc_name)
2677                         modest_window_set_active_account (window, modest_acc_name);
2678         }
2679
2680         g_object_unref (modest_server_account);
2681 }
2682
2683
2684 static void
2685 folder_refreshed_cb (ModestMailOperation *mail_op,
2686                      TnyFolder *folder,
2687                      gpointer user_data)
2688 {
2689         ModestMainWindow *win = NULL;
2690         GtkWidget *folder_view, *header_view;
2691         const GError *error;
2692
2693         g_return_if_fail (TNY_IS_FOLDER (folder));
2694
2695         win = MODEST_MAIN_WINDOW (user_data);
2696
2697         /* Check if the operation failed due to memory low conditions */
2698         error = modest_mail_operation_get_error (mail_op);
2699         if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
2700             error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
2701                 modest_platform_run_information_dialog (GTK_WINDOW (win),
2702                                                         _KR("memr_ib_operation_disabled"),
2703                                                         TRUE);
2704                 return;
2705         }
2706
2707         folder_view =
2708                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2709         header_view =
2710                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2711
2712         if (folder_view) {
2713                 TnyFolderStore *current_folder;
2714
2715                 current_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2716                 if (current_folder) {
2717                         gboolean different = ((TnyFolderStore *) folder != current_folder);
2718                         g_object_unref (current_folder);
2719                         if (different)
2720                                 return;
2721                 }
2722         }
2723
2724         /* Check if folder is empty and set headers view contents style */
2725         if ((tny_folder_get_all_count (folder) == 0) ||
2726             modest_header_view_is_empty (MODEST_HEADER_VIEW (header_view)))
2727                 modest_main_window_set_contents_style (win,
2728                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2729 }
2730
2731 void
2732 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2733                                                TnyFolderStore *folder_store,
2734                                                gboolean selected,
2735                                                ModestMainWindow *main_window)
2736 {
2737         GtkWidget *header_view;
2738
2739         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2740
2741         header_view = modest_main_window_get_child_widget(main_window,
2742                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2743         if (!header_view)
2744                 return;
2745
2746
2747         if (TNY_IS_ACCOUNT (folder_store)) {
2748                 if (selected) {
2749                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2750
2751                         /* Show account details */
2752                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2753                 }
2754         } else {
2755                 if (TNY_IS_FOLDER (folder_store) && selected) {
2756                         TnyAccount *account;
2757
2758                         /* Update the active account */
2759                         account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2760                         if (account) {
2761                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2762                                 g_object_unref (account);
2763                                 account = NULL;
2764                         }
2765
2766                         /* Set the header style by default, it could
2767                            be changed later by the refresh callback to
2768                            empty */
2769                         modest_main_window_set_contents_style (main_window,
2770                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2771
2772                         /* Set folder on header view. This function
2773                            will call tny_folder_refresh_async so we
2774                            pass a callback that will be called when
2775                            finished. We use that callback to set the
2776                            empty view if there are no messages */
2777                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2778                                                        TNY_FOLDER (folder_store),
2779                                                        TRUE,
2780                                                        MODEST_WINDOW (main_window),
2781                                                        folder_refreshed_cb,
2782                                                        main_window);
2783
2784                         /* Restore configuration. We need to do this
2785                            *after* the set_folder because the widget
2786                            memory asks the header view about its
2787                            folder  */
2788                         modest_widget_memory_restore (modest_runtime_get_conf (),
2789                                                       G_OBJECT(header_view),
2790                                                       MODEST_CONF_HEADER_VIEW_KEY);
2791                 } else {
2792                         /* No need to save the header view
2793                            configuration for Maemo because it only
2794                            saves the sorting stuff and that it's
2795                            already being done by the sort
2796                            dialog. Remove it when the GNOME version
2797                            has the same behaviour */
2798 #ifdef MODEST_TOOLKIT_GTK
2799                         if (modest_main_window_get_contents_style (main_window) ==
2800                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2801                                 modest_widget_memory_save (modest_runtime_get_conf (), 
2802                                                            G_OBJECT (header_view),
2803                                                            MODEST_CONF_HEADER_VIEW_KEY);
2804 #endif
2805                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2806                 }
2807         }
2808
2809         /* Update dimming state */
2810         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2811         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2812 }
2813
2814 void
2815 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2816                                      ModestWindow *win)
2817 {
2818         GtkWidget *dialog;
2819         gchar *txt, *item;
2820         gboolean online;
2821
2822         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2823
2824         online = tny_device_is_online (modest_runtime_get_device());
2825
2826         if (online) {
2827                 /* already online -- the item is simply not there... */
2828                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2829                                                  GTK_DIALOG_MODAL,
2830                                                  GTK_MESSAGE_WARNING,
2831                                                  GTK_BUTTONS_NONE,
2832                                                  _("The %s you selected cannot be found"),
2833                                                  item);
2834                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2835                 gtk_dialog_run (GTK_DIALOG(dialog));
2836         } else {
2837                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2838                                                       GTK_WINDOW (win),
2839                                                       GTK_DIALOG_MODAL,
2840                                                       _("mcen_bd_dialog_cancel"),
2841                                                       GTK_RESPONSE_REJECT,
2842                                                       _("mcen_bd_dialog_ok"),
2843                                                       GTK_RESPONSE_ACCEPT,
2844                                                       NULL);
2845                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2846                                          "Do you want to get online?"), item);
2847                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2848                                     gtk_label_new (txt), FALSE, FALSE, 0);
2849                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2850                 g_free (txt);
2851
2852                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2853                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2854                         /* TODO: Comment about why is this commented out: */
2855                         /* modest_platform_connect_and_wait (); */
2856                 }
2857         }
2858         gtk_widget_destroy (dialog);
2859 }
2860
2861 void
2862 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2863                                      ModestWindow *win)
2864 {
2865         /* g_debug ("%s %s", __FUNCTION__, link); */
2866 }
2867
2868
2869 void
2870 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2871                                         ModestWindow *win)
2872 {
2873         modest_platform_activate_uri (link);
2874 }
2875
2876 void
2877 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2878                                           ModestWindow *win)
2879 {
2880         modest_platform_show_uri_popup (link);
2881 }
2882
2883 void
2884 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2885                                              ModestWindow *win)
2886 {
2887         /* we check for low-mem; in that case, show a warning, and don't allow
2888          * viewing attachments
2889          */
2890         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2891                 return;
2892
2893         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2894 }
2895
2896 void
2897 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2898                                           const gchar *address,
2899                                           ModestWindow *win)
2900 {
2901         /* g_debug ("%s %s", __FUNCTION__, address); */
2902 }
2903
2904 static void
2905 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2906                       TnyMsg *saved_draft,
2907                       gpointer user_data)
2908 {
2909         ModestMsgEditWindow *edit_window;
2910
2911         /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
2912 #ifndef MODEST_TOOLKIT_HILDON2
2913         ModestMainWindow *win;
2914
2915         /* FIXME. Make the header view sensitive again. This is a
2916          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2917          * for details */
2918         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2919                                          modest_runtime_get_window_mgr(), FALSE));
2920         if (win != NULL) {
2921                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2922                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2923                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2924         }
2925 #endif
2926
2927         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2928
2929         /* Set draft is there was no error */
2930         if (!modest_mail_operation_get_error (mail_op))
2931                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2932
2933         g_object_unref(edit_window);
2934 }
2935
2936 static gboolean
2937 enough_space_for_message (ModestMsgEditWindow *edit_window,
2938                           MsgData *data)
2939 {
2940         guint64 available_disk, expected_size;
2941         gint parts_count;
2942         guint64 parts_size;
2943
2944         /* Check size */
2945         available_disk = modest_utils_get_available_space (NULL);
2946         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2947         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2948                                                       data->html_body,
2949                                                       parts_count,
2950                                                       parts_size);
2951
2952         /* Double check: disk full condition or message too big */
2953         if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
2954             expected_size > available_disk) {
2955                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
2956                 modest_platform_information_banner (NULL, NULL, msg);
2957                 g_free (msg);
2958
2959                 return FALSE;
2960         }
2961
2962         /*
2963          * djcb: if we're in low-memory state, we only allow for
2964          * saving messages smaller than
2965          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2966          * should still allow for sending anything critical...
2967          */
2968         if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
2969             modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
2970                 return FALSE;
2971
2972         /*
2973          * djcb: we also make sure that the attachments are smaller than the max size
2974          * this is for the case where we'd try to forward a message with attachments
2975          * bigger than our max allowed size, or sending an message from drafts which
2976          * somehow got past our checks when attaching.
2977          */
2978         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2979                 modest_platform_run_information_dialog (
2980                         GTK_WINDOW(edit_window),
2981                         _("mail_ib_error_attachment_size"),
2982                         TRUE);
2983                 return FALSE;
2984         }
2985
2986         return TRUE;
2987 }
2988
2989 gboolean
2990 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2991 {
2992         TnyTransportAccount *transport_account;
2993         ModestMailOperation *mail_operation;
2994         MsgData *data;
2995         gchar *account_name;
2996         ModestAccountMgr *account_mgr;
2997         gboolean had_error = FALSE;
2998         ModestMainWindow *win = NULL;
2999
3000         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
3001
3002         data = modest_msg_edit_window_get_msg_data (edit_window);
3003
3004         /* Check size */
3005         if (!enough_space_for_message (edit_window, data)) {
3006                 modest_msg_edit_window_free_msg_data (edit_window, data);
3007                 return FALSE;
3008         }
3009
3010         account_name = g_strdup (data->account_name);
3011         account_mgr = modest_runtime_get_account_mgr();
3012         if (!account_name)
3013                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3014         if (!account_name)
3015                 account_name = modest_account_mgr_get_default_account (account_mgr);
3016         if (!account_name) {
3017                 g_printerr ("modest: no account found\n");
3018                 modest_msg_edit_window_free_msg_data (edit_window, data);
3019                 return FALSE;
3020         }
3021
3022         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
3023                 account_name = g_strdup (data->account_name);
3024         }
3025
3026         transport_account =
3027                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3028                                       (modest_runtime_get_account_store (),
3029                                        account_name,
3030                                        TNY_ACCOUNT_TYPE_TRANSPORT));
3031         if (!transport_account) {
3032                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
3033                 g_free (account_name);
3034                 modest_msg_edit_window_free_msg_data (edit_window, data);
3035                 return FALSE;
3036         }
3037
3038         /* Create the mail operation */
3039         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
3040                                                                         NULL, NULL);
3041         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3042
3043         modest_mail_operation_save_to_drafts (mail_operation,
3044                                               transport_account,
3045                                               data->draft_msg,
3046                                               data->from,
3047                                               data->to, 
3048                                               data->cc, 
3049                                               data->bcc,
3050                                               data->subject,
3051                                               data->plain_body,
3052                                               data->html_body,
3053                                               data->attachments,
3054                                               data->images,
3055                                               data->priority_flags,
3056                                               data->references,
3057                                               data->in_reply_to,
3058                                               on_save_to_drafts_cb,
3059                                               g_object_ref(edit_window));
3060
3061 #ifdef MODEST_TOOLKIT_HILDON2
3062         /* In hildon2 we always show the information banner on saving to drafts.
3063          * It will be a system information banner in this case.
3064          */
3065         gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3066         modest_platform_information_banner (NULL, NULL, text);
3067         g_free (text);
3068 #else
3069         /* Use the main window as the parent of the banner, if the
3070            main window does not exist it won't be shown, if the parent
3071            window exists then it's properly shown. We don't use the
3072            editor window because it could be closed (save to drafts
3073            could happen after closing the window */
3074         win = (ModestMainWindow *)
3075                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
3076         if (win) {
3077                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3078                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
3079                 g_free (text);
3080         }
3081 #endif
3082         modest_msg_edit_window_set_modified (edit_window, FALSE);
3083
3084         /* Frees */
3085         g_free (account_name);
3086         g_object_unref (G_OBJECT (transport_account));
3087         g_object_unref (G_OBJECT (mail_operation));
3088
3089         modest_msg_edit_window_free_msg_data (edit_window, data);
3090
3091         /* ** FIXME **
3092          * If the drafts folder is selected then make the header view
3093          * insensitive while the message is being saved to drafts
3094          * (it'll be sensitive again in on_save_to_drafts_cb()). This
3095          * is not very clean but it avoids letting the drafts folder
3096          * in an inconsistent state: the user could edit the message
3097          * being saved and undesirable things would happen.
3098          * In the average case the user won't notice anything at
3099          * all. In the worst case (the user is editing a really big
3100          * file from Drafts) the header view will be insensitive
3101          * during the saving process (10 or 20 seconds, depending on
3102          * the message). Anyway this is just a quick workaround: once
3103          * we find a better solution it should be removed
3104          * See NB#65125 (commend #18) for details.
3105          */
3106         if (!had_error && win != NULL) {
3107                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
3108                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
3109                 if (view != NULL) {
3110                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
3111                         if (folder) {
3112                                 if (modest_tny_folder_is_local_folder(folder)) {
3113                                         TnyFolderType folder_type;
3114                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
3115                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
3116                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
3117                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3118                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
3119                                         }
3120                                 }
3121                         }
3122                         if (folder != NULL) g_object_unref(folder);
3123                 }
3124         }
3125
3126         return !had_error;
3127 }
3128
3129 /* For instance, when clicking the Send toolbar button when editing a message: */
3130 gboolean
3131 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3132 {
3133         TnyTransportAccount *transport_account = NULL;
3134         gboolean had_error = FALSE;
3135         MsgData *data;
3136         ModestAccountMgr *account_mgr;
3137         gchar *account_name;
3138         ModestMailOperation *mail_operation;
3139         gchar *recipients;
3140
3141         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3142
3143         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
3144                 return TRUE;
3145
3146         data = modest_msg_edit_window_get_msg_data (edit_window);
3147
3148         recipients = g_strconcat (data->to?data->to:"", 
3149                                   data->cc?data->cc:"",
3150                                   data->bcc?data->bcc:"",
3151                                   NULL);
3152         if (recipients == NULL || recipients[0] == '\0') {
3153                 /* Empty subject -> no send */
3154                 g_free (recipients);
3155                 modest_msg_edit_window_free_msg_data (edit_window, data);
3156                 return FALSE;
3157         }
3158         g_free (recipients);
3159
3160         /* Check size */
3161         if (!enough_space_for_message (edit_window, data)) {
3162                 modest_msg_edit_window_free_msg_data (edit_window, data);
3163                 return FALSE;
3164         }
3165
3166         account_mgr = modest_runtime_get_account_mgr();
3167         account_name = g_strdup (data->account_name);
3168         if (!account_name)
3169                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3170
3171         if (!account_name)
3172                 account_name = modest_account_mgr_get_default_account (account_mgr);
3173
3174         if (!account_name) {
3175                 modest_msg_edit_window_free_msg_data (edit_window, data);
3176                 /* Run account setup wizard */
3177                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3178                         return TRUE;
3179                 }
3180         }
3181
3182         /* Get the currently-active transport account for this modest account: */
3183         if (account_name && strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3184                 transport_account =
3185                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3186                                               (modest_runtime_get_account_store (),
3187                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3188         }
3189
3190         if (!transport_account) {
3191                 modest_msg_edit_window_free_msg_data (edit_window, data);
3192                 /* Run account setup wizard */
3193                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3194                         return TRUE;
3195         }
3196
3197
3198         /* Create the mail operation */
3199         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3200         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3201
3202         modest_mail_operation_send_new_mail (mail_operation,
3203                                              transport_account,
3204                                              data->draft_msg,
3205                                              data->from,
3206                                              data->to,
3207                                              data->cc,
3208                                              data->bcc,
3209                                              data->subject,
3210                                              data->plain_body,
3211                                              data->html_body,
3212                                              data->attachments,
3213                                              data->images,
3214                                              data->references,
3215                                              data->in_reply_to,
3216                                              data->priority_flags);
3217
3218         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3219                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3220
3221         if (modest_mail_operation_get_error (mail_operation) != NULL) {
3222                 const GError *error = modest_mail_operation_get_error (mail_operation);
3223                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3224                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3225                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3226                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3227                         had_error = TRUE;
3228                 }
3229         }
3230
3231         /* Free data: */
3232         g_free (account_name);
3233         g_object_unref (G_OBJECT (transport_account));
3234         g_object_unref (G_OBJECT (mail_operation));
3235
3236         modest_msg_edit_window_free_msg_data (edit_window, data);
3237
3238         if (!had_error) {
3239                 modest_msg_edit_window_set_sent (edit_window, TRUE);
3240
3241                 /* Save settings and close the window: */
3242                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3243         }
3244
3245         return !had_error;
3246 }
3247
3248 void
3249 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3250                                   ModestMsgEditWindow *window)
3251 {
3252         ModestMsgEditFormatState *format_state = NULL;
3253
3254         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3255         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3256
3257         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3258                 return;
3259
3260         format_state = modest_msg_edit_window_get_format_state (window);
3261         g_return_if_fail (format_state != NULL);
3262
3263         format_state->bold = gtk_toggle_action_get_active (action);
3264         modest_msg_edit_window_set_format_state (window, format_state);
3265         g_free (format_state);
3266
3267 }
3268
3269 void
3270 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3271                                      ModestMsgEditWindow *window)
3272 {
3273         ModestMsgEditFormatState *format_state = NULL;
3274
3275         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3276         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3277
3278         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3279                 return;
3280
3281         format_state = modest_msg_edit_window_get_format_state (window);
3282         g_return_if_fail (format_state != NULL);
3283
3284         format_state->italics = gtk_toggle_action_get_active (action);
3285         modest_msg_edit_window_set_format_state (window, format_state);
3286         g_free (format_state);
3287
3288 }
3289
3290 void
3291 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3292                                      ModestMsgEditWindow *window)
3293 {
3294         ModestMsgEditFormatState *format_state = NULL;
3295
3296         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3297         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3298
3299         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3300                 return;
3301
3302         format_state = modest_msg_edit_window_get_format_state (window);
3303         g_return_if_fail (format_state != NULL);
3304
3305         format_state->bullet = gtk_toggle_action_get_active (action);
3306         modest_msg_edit_window_set_format_state (window, format_state);
3307         g_free (format_state);
3308
3309 }
3310
3311 void
3312 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3313                                      GtkRadioAction *selected,
3314                                      ModestMsgEditWindow *window)
3315 {
3316         ModestMsgEditFormatState *format_state = NULL;
3317         GtkJustification value;
3318
3319         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3320
3321         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3322                 return;
3323
3324         value = gtk_radio_action_get_current_value (selected);
3325
3326         format_state = modest_msg_edit_window_get_format_state (window);
3327         g_return_if_fail (format_state != NULL);
3328
3329         format_state->justification = value;
3330         modest_msg_edit_window_set_format_state (window, format_state);
3331         g_free (format_state);
3332 }
3333
3334 void
3335 modest_ui_actions_on_select_editor_color (GtkAction *action,
3336                                           ModestMsgEditWindow *window)
3337 {
3338         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3339         g_return_if_fail (GTK_IS_ACTION (action));
3340
3341         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3342                 return;
3343
3344         modest_msg_edit_window_select_color (window);
3345 }
3346
3347 void
3348 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3349                                                      ModestMsgEditWindow *window)
3350 {
3351         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3352         g_return_if_fail (GTK_IS_ACTION (action));
3353
3354         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3355                 return;
3356
3357         modest_msg_edit_window_select_background_color (window);
3358 }
3359
3360 void
3361 modest_ui_actions_on_insert_image (GObject *object,
3362                                    ModestMsgEditWindow *window)
3363 {
3364         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3365
3366
3367         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3368                 return;
3369
3370         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3371                 return;
3372
3373         modest_msg_edit_window_insert_image (window);
3374 }
3375
3376 void
3377 modest_ui_actions_on_attach_file (GtkAction *action,
3378                                   ModestMsgEditWindow *window)
3379 {
3380         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3381         g_return_if_fail (GTK_IS_ACTION (action));
3382
3383         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3384                 return;
3385
3386         modest_msg_edit_window_offer_attach_file (window);
3387 }
3388
3389 void
3390 modest_ui_actions_on_remove_attachments (GtkAction *action,
3391                                          ModestMsgEditWindow *window)
3392 {
3393         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3394
3395         modest_msg_edit_window_remove_attachments (window, NULL);
3396 }
3397
3398 static void
3399 do_create_folder_cb (ModestMailOperation *mail_op,
3400                      TnyFolderStore *parent_folder,
3401                      TnyFolder *new_folder,
3402                      gpointer user_data)
3403 {
3404         gchar *suggested_name = (gchar *) user_data;
3405         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3406         const GError *error;
3407
3408         error = modest_mail_operation_get_error (mail_op);
3409         if (error) {
3410                 gboolean disk_full = FALSE;
3411                 TnyAccount *account;
3412                 /* Show an error. If there was some problem writing to
3413                    disk, show it, otherwise show the generic folder
3414                    create error. We do it here and not in an error
3415                    handler because the call to do_create_folder will
3416                    stop the main loop in a gtk_dialog_run and then,
3417                    the message won't be shown until that dialog is
3418                    closed */
3419                 account = modest_mail_operation_get_account (mail_op);
3420                 if (account) {
3421                         disk_full =
3422                                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3423                                                                                 (GtkWidget *) source_win,
3424                                                                                 (GError *) error,
3425                                                                                 account,
3426                                                                                 _("mail_in_ui_folder_create_error_memory"));
3427                         g_object_unref (account);
3428                 }
3429                 if (!disk_full) {
3430                         /* Show an error and try again if there is no
3431                            full memory condition */
3432                         modest_platform_information_banner ((GtkWidget *) source_win, NULL,
3433                                                             _("mail_in_ui_folder_create_error"));
3434                         do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3435                 }
3436
3437         } else {
3438                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3439                  * FIXME: any other? */
3440                 GtkWidget *folder_view;
3441
3442                 if (MODEST_IS_MAIN_WINDOW(source_win))
3443                         folder_view =
3444                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3445                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3446                 else
3447                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3448                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3449
3450                 /* Select the newly created folder. It could happen
3451                    that the widget is no longer there (i.e. the window
3452                    has been destroyed, so we need to check this */
3453                 if (folder_view)
3454                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3455                                                           new_folder, FALSE);
3456                 g_object_unref (new_folder);
3457         }
3458         /* Free. Note that the first time it'll be NULL so noop */
3459         g_free (suggested_name);
3460         g_object_unref (source_win);
3461 }
3462
3463 typedef struct {
3464         gchar *folder_name;
3465         TnyFolderStore *parent;
3466 } CreateFolderConnect;
3467
3468 static void
3469 do_create_folder_performer (gboolean canceled,
3470                          GError *err,
3471                          GtkWindow *parent_window,
3472                          TnyAccount *account,
3473                          gpointer user_data)
3474 {
3475         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
3476         ModestMailOperation *mail_op;
3477
3478         if (canceled || err) {
3479                 /* In disk full conditions we could get this error here */
3480                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3481                                                                 (GtkWidget *) parent_window, err,
3482                                                                 NULL, _("mail_in_ui_folder_create_error_memory"));
3483
3484                 /* This happens if we have selected the outbox folder
3485                    as the parent */
3486                 if (err && err->code == TNY_SERVICE_ERROR_UNKNOWN &&
3487                     TNY_IS_MERGE_FOLDER (helper->parent)) {
3488                         /* Show an error and retry */
3489                         modest_platform_information_banner ((GtkWidget *) parent_window,
3490                                                             NULL,
3491                                                             _("mail_in_ui_folder_create_error"));
3492
3493                         do_create_folder (parent_window, helper->parent, helper->folder_name);
3494                 }
3495
3496                 goto frees;
3497         }
3498
3499         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3500         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3501                                          mail_op);
3502         modest_mail_operation_create_folder (mail_op,
3503                                              helper->parent,
3504                                              (const gchar *) helper->folder_name,
3505                                              do_create_folder_cb,
3506                                              g_strdup (helper->folder_name));
3507         g_object_unref (mail_op);
3508
3509  frees:
3510         if (helper->parent)
3511                 g_object_unref (helper->parent);
3512         if (helper->folder_name)
3513                 g_free (helper->folder_name);
3514         g_slice_free (CreateFolderConnect, helper);
3515 }
3516
3517
3518 static void
3519 do_create_folder (GtkWindow *parent_window,
3520                   TnyFolderStore *suggested_parent,
3521                   const gchar *suggested_name)
3522 {
3523         gint result;
3524         gchar *folder_name = NULL;
3525         TnyFolderStore *parent_folder = NULL;
3526
3527         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3528                                                         suggested_parent,
3529                                                         (gchar *) suggested_name,
3530                                                         &folder_name,
3531                                                         &parent_folder);
3532
3533         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3534                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3535                 helper->folder_name = g_strdup (folder_name);
3536                 helper->parent = g_object_ref (parent_folder);
3537
3538                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3539                                                                TRUE,
3540                                                                parent_folder,
3541                                                                do_create_folder_performer,
3542                                                                helper);
3543         }
3544
3545         if (folder_name)
3546                 g_free (folder_name);
3547         if (parent_folder)
3548                 g_object_unref (parent_folder);
3549 }
3550
3551 static void
3552 modest_ui_actions_create_folder(GtkWidget *parent_window,
3553                                 GtkWidget *folder_view,
3554                                 TnyFolderStore *parent_folder)
3555 {
3556         if (!parent_folder) {
3557 #ifdef MODEST_TOOLKIT_HILDON2
3558                 ModestTnyAccountStore *acc_store;
3559
3560                 acc_store = modest_runtime_get_account_store ();
3561
3562                 parent_folder = (TnyFolderStore *)
3563                         modest_tny_account_store_get_local_folders_account (acc_store);
3564 #else
3565                 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3566 #endif
3567         }
3568
3569         if (parent_folder) {
3570                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3571                 g_object_unref (parent_folder);
3572         }
3573 }
3574
3575 void
3576 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3577 {
3578
3579         g_return_if_fail (MODEST_IS_WINDOW(window));
3580
3581         if (MODEST_IS_MAIN_WINDOW (window)) {
3582                 GtkWidget *folder_view;
3583
3584                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3585                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3586                 if (!folder_view)
3587                         return;
3588
3589                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3590 #ifdef MODEST_TOOLKIT_HILDON2
3591         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3592                 GtkWidget *folder_view;
3593
3594                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3595                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3596 #endif
3597         } else {
3598                 g_assert_not_reached ();
3599         }
3600 }
3601
3602 static void
3603 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3604                                                gpointer user_data)
3605 {
3606         const GError *error = NULL;
3607         gchar *message = NULL;
3608         gboolean mem_full;
3609         TnyAccount *account = modest_mail_operation_get_account (mail_op);
3610
3611         /* Get error message */
3612         error = modest_mail_operation_get_error (mail_op);
3613         if (!error)
3614                 g_return_if_reached ();
3615
3616         mem_full = modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
3617                                                                 (GError *) error, account);
3618         if (mem_full) {
3619                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3620         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3621                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3622                 message = _CS("ckdg_ib_folder_already_exists");
3623         } else if (error->domain == TNY_ERROR_DOMAIN &&
3624                    error->code == TNY_SERVICE_ERROR_STATE) {
3625                 /* This means that the folder is already in use (a
3626                    message is opened for example */
3627                 message = _("emev_ni_internal_error");
3628         } else {
3629                 message = _CS("ckdg_ib_unable_to_rename");
3630         }
3631
3632         /* We don't set a parent for the dialog because the dialog
3633            will be destroyed so the banner won't appear */
3634         modest_platform_information_banner (NULL, NULL, message);
3635
3636         if (account)
3637                 g_object_unref (account);
3638         if (mem_full)
3639                 g_free (message);
3640 }
3641
3642 typedef struct {
3643         TnyFolderStore *folder;
3644         gchar *new_name;
3645 } RenameFolderInfo;
3646
3647 static void
3648 on_rename_folder_cb (ModestMailOperation *mail_op,
3649                      TnyFolder *new_folder,
3650                      gpointer user_data)
3651 {
3652         ModestFolderView *folder_view;
3653
3654         /* If the window was closed when renaming a folder, or if
3655          * it's not a main window this will happen */
3656         if (!MODEST_IS_FOLDER_VIEW (user_data))
3657                 return;
3658
3659         folder_view = MODEST_FOLDER_VIEW (user_data);
3660         /* Note that if the rename fails new_folder will be NULL */
3661         if (new_folder) {
3662                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3663         } else {
3664                 modest_folder_view_select_first_inbox_or_local (folder_view);
3665         }
3666         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3667 }
3668
3669 static void
3670 on_rename_folder_performer (gboolean canceled,
3671                             GError *err,
3672                             GtkWindow *parent_window,
3673                             TnyAccount *account,
3674                             gpointer user_data)
3675 {
3676         ModestMailOperation *mail_op = NULL;
3677         GtkTreeSelection *sel = NULL;
3678         GtkWidget *folder_view = NULL;
3679         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3680
3681         if (canceled || err) {
3682                 /* In disk full conditions we could get this error here */
3683                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3684                                                                 (GtkWidget *) parent_window, err,
3685                                                                 account, NULL);
3686         } else {
3687
3688                 mail_op =
3689                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3690                                         modest_ui_actions_rename_folder_error_handler,
3691                                         parent_window, NULL);
3692
3693                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3694                                 mail_op);
3695
3696                 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3697
3698                         folder_view = modest_main_window_get_child_widget (
3699                                 MODEST_MAIN_WINDOW (parent_window),
3700                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3701                 }
3702 #ifdef MODEST_TOOLKIT_HILDON2
3703                 else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3704                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3705                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3706                 }
3707 #endif
3708
3709                 /* Clear the folders view */
3710                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3711                 gtk_tree_selection_unselect_all (sel);
3712
3713                 /* Actually rename the folder */
3714                 modest_mail_operation_rename_folder (mail_op,
3715                                                      TNY_FOLDER (data->folder),
3716                                                      (const gchar *) (data->new_name),
3717                                                      on_rename_folder_cb,
3718                                                      folder_view);
3719                 g_object_unref (mail_op);
3720         }
3721
3722         g_object_unref (data->folder);
3723         g_free (data->new_name);
3724         g_free (data);
3725 }
3726
3727 void
3728 modest_ui_actions_on_rename_folder (GtkAction *action,
3729                                      ModestWindow *window)
3730 {
3731         modest_ui_actions_on_edit_mode_rename_folder (window);
3732 }
3733
3734 gboolean
3735 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3736 {
3737         TnyFolderStore *folder;
3738         GtkWidget *folder_view;
3739         gboolean do_rename = TRUE;
3740
3741         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3742
3743         if (MODEST_IS_MAIN_WINDOW (window)) {
3744                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3745                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3746                 if (!folder_view)
3747                         return FALSE;
3748
3749 #ifdef MODEST_TOOLKIT_HILDON2
3750         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3751                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3752 #endif
3753         } else {
3754                 return FALSE;
3755         }
3756
3757         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3758
3759         if (!folder)
3760                 return FALSE;
3761
3762         if (TNY_IS_FOLDER (folder)) {
3763                 gchar *folder_name = NULL;
3764                 gint response;
3765                 const gchar *current_name;
3766                 TnyFolderStore *parent;
3767
3768                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3769                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3770                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3771                                                                      parent, current_name,
3772                                                                      &folder_name);
3773                 g_object_unref (parent);
3774
3775                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3776                         do_rename = FALSE;
3777                 } else {
3778                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3779                         rename_folder_data->folder = g_object_ref (folder);
3780                         rename_folder_data->new_name = folder_name;
3781                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3782                                         folder, on_rename_folder_performer, rename_folder_data);
3783                 }
3784         }
3785         g_object_unref (folder);
3786         return do_rename;
3787 }
3788
3789 static void
3790 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3791                                                gpointer user_data)
3792 {
3793         GObject *win = modest_mail_operation_get_source (mail_op);
3794
3795         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3796                                                 _("mail_in_ui_folder_delete_error"),
3797                                                 FALSE);
3798         g_object_unref (win);
3799 }
3800
3801 typedef struct {
3802         TnyFolderStore *folder;
3803         gboolean move_to_trash;
3804 } DeleteFolderInfo;
3805
3806 static void
3807 on_delete_folder_cb (gboolean canceled,
3808                   GError *err,
3809                   GtkWindow *parent_window,
3810                   TnyAccount *account,
3811                   gpointer user_data)
3812 {
3813         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3814         GtkWidget *folder_view;
3815         ModestMailOperation *mail_op;
3816         GtkTreeSelection *sel;
3817
3818         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
3819                 /* Note that the connection process can fail due to
3820                    memory low conditions as it can not successfully
3821                    store the summary */
3822                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3823                                                                      (GtkWidget*) parent_window, err,
3824                                                                      account, NULL))
3825                         g_debug ("Error connecting when trying to delete a folder");
3826                 g_object_unref (G_OBJECT (info->folder));
3827                 g_free (info);
3828                 return;
3829         }
3830
3831         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
3832                 folder_view = modest_main_window_get_child_widget (
3833                         MODEST_MAIN_WINDOW (parent_window),
3834                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3835 #ifdef MODEST_TOOLKIT_HILDON2
3836         } else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3837                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
3838 #endif
3839         } else {
3840                 g_object_unref (G_OBJECT (info->folder));
3841                 g_free (info);
3842                 return;
3843         }
3844
3845         /* Unselect the folder before deleting it to free the headers */
3846         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3847         gtk_tree_selection_unselect_all (sel);
3848
3849         /* Create the mail operation */
3850         mail_op =
3851                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3852                                 modest_ui_actions_delete_folder_error_handler,
3853                                 NULL, NULL);
3854
3855         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3856                         mail_op);
3857         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3858
3859         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3860
3861         g_object_unref (mail_op);
3862         g_object_unref (info->folder);
3863         g_free (info);
3864 }
3865
3866 static gboolean
3867 delete_folder (ModestWindow *window, gboolean move_to_trash)
3868 {
3869         TnyFolderStore *folder;
3870         GtkWidget *folder_view;
3871         gint response;
3872         gchar *message;
3873
3874         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3875
3876         if (MODEST_IS_MAIN_WINDOW (window)) {
3877
3878                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3879                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3880 #ifdef MODEST_TOOLKIT_HILDON2
3881         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3882                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3883 #endif
3884         } else {
3885                 return FALSE;
3886         }
3887         if (!folder_view)
3888                 return FALSE;
3889
3890         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3891
3892         if (!folder)
3893                 return FALSE;
3894
3895         /* Show an error if it's an account */
3896         if (!TNY_IS_FOLDER (folder)) {
3897                 modest_platform_run_information_dialog (GTK_WINDOW (window),
3898                                                         _("mail_in_ui_folder_delete_error"),
3899                                                         FALSE);
3900                 g_object_unref (G_OBJECT (folder));
3901                 return FALSE;
3902         }
3903
3904         /* Ask the user */
3905         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
3906                                     tny_folder_get_name (TNY_FOLDER (folder)));
3907         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
3908                                                             (const gchar *) message);
3909         g_free (message);
3910
3911         if (response == GTK_RESPONSE_OK) {
3912                 TnyAccount *account = NULL;
3913                 DeleteFolderInfo *info = NULL;
3914                 info = g_new0(DeleteFolderInfo, 1);
3915                 info->folder = g_object_ref (folder);
3916                 info->move_to_trash = move_to_trash;
3917
3918                 account = tny_folder_get_account (TNY_FOLDER (folder));
3919                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
3920                                                                TRUE,
3921                                                                TNY_FOLDER_STORE (account),
3922                                                                on_delete_folder_cb, info);
3923                 g_object_unref (account);
3924                 g_object_unref (folder);
3925                 return TRUE;
3926         } else {
3927                 return FALSE;
3928         }
3929 }
3930
3931 void
3932 modest_ui_actions_on_delete_folder (GtkAction *action,
3933                                     ModestWindow *window)
3934 {
3935         modest_ui_actions_on_edit_mode_delete_folder (window);
3936 }
3937
3938 gboolean
3939 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
3940 {
3941         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
3942
3943         return delete_folder (window, FALSE);
3944 }
3945
3946 void
3947 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3948 {
3949         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3950
3951         delete_folder (MODEST_WINDOW (main_window), TRUE);
3952 }
3953
3954
3955 typedef struct _PasswordDialogFields {
3956         GtkWidget *username;
3957         GtkWidget *password;
3958         GtkWidget *dialog;
3959 } PasswordDialogFields;
3960
3961 static void
3962 password_dialog_check_field (GtkEditable *editable,
3963                              PasswordDialogFields *fields)
3964 {
3965         const gchar *value;
3966         gboolean any_value_empty = FALSE;
3967
3968 #ifdef MODEST_TOOLKIT_HILDON2
3969         value = hildon_entry_get_text (HILDON_ENTRY (fields->username));
3970 #else
3971         value = gtk_entry_get_text (GTK_ENTRY (fields->username));
3972 #endif
3973         if ((value == NULL) || value[0] == '\0') {
3974                 any_value_empty = TRUE;
3975         }
3976 #ifdef MODEST_TOOLKIT_HILDON2
3977         value = hildon_entry_get_text (HILDON_ENTRY (fields->password));
3978 #else
3979         value = gtk_entry_get_text (GTK_ENTRY (fields->password));
3980 #endif
3981         if ((value == NULL) || value[0] == '\0') {
3982                 any_value_empty = TRUE;
3983         }
3984         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3985 }
3986
3987 void
3988 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
3989                                          const gchar* server_account_name,
3990                                          gchar **username,
3991                                          gchar **password,
3992                                          gboolean *cancel,
3993                                          gboolean *remember,
3994                                          ModestMainWindow *main_window)
3995 {
3996         g_return_if_fail(server_account_name);
3997         gboolean completed = FALSE;
3998         PasswordDialogFields *fields = NULL;
3999
4000         /* Initalize output parameters: */
4001         if (cancel)
4002                 *cancel = FALSE;
4003
4004         if (remember)
4005                 *remember = TRUE;
4006
4007 #ifndef MODEST_TOOLKIT_GTK
4008         /* Maemo uses a different (awkward) button order,
4009          * It should probably just use gtk_alternative_dialog_button_order ().
4010          */
4011 #ifdef MODEST_TOOLKIT_HILDON2
4012         GtkWidget *dialog =
4013                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4014                                              NULL,
4015                                              GTK_DIALOG_MODAL,
4016                                              _HL("wdgt_bd_done"),
4017                                              GTK_RESPONSE_ACCEPT,
4018                                              NULL);
4019         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
4020                                         HILDON_MARGIN_DOUBLE);
4021 #else
4022         GtkWidget *dialog =
4023                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4024                                              NULL,
4025                                              GTK_DIALOG_MODAL,
4026                                              _("mcen_bd_dialog_ok"),
4027                                              GTK_RESPONSE_ACCEPT,
4028                                              _("mcen_bd_dialog_cancel"),
4029                                              GTK_RESPONSE_REJECT,
4030                                              NULL);
4031 #endif /* MODEST_TOOLKIT_HILDON2 */
4032 #else
4033         GtkWidget *dialog =
4034                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4035                                              NULL,
4036                                              GTK_DIALOG_MODAL,
4037                                              GTK_STOCK_CANCEL,
4038                                              GTK_RESPONSE_REJECT,
4039                                              GTK_STOCK_OK,
4040                                              GTK_RESPONSE_ACCEPT,
4041                                              NULL);
4042 #endif /* MODEST_TOOLKIT_GTK */
4043
4044         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
4045
4046         gchar *server_name = modest_account_mgr_get_server_account_hostname (
4047                 modest_runtime_get_account_mgr(), server_account_name);
4048         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
4049                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
4050                 if (cancel)
4051                         *cancel = TRUE;
4052                 gtk_widget_destroy (dialog);
4053                 return;
4054         }
4055
4056         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
4057         GtkWidget *label = gtk_label_new (txt);
4058         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
4059         g_free (txt);
4060         g_free (server_name);
4061         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
4062                             FALSE, FALSE, 0);
4063         server_name = NULL;
4064
4065         /* username: */
4066         gchar *initial_username = modest_account_mgr_get_server_account_username (
4067                 modest_runtime_get_account_mgr(), server_account_name);
4068
4069 #ifdef MODEST_TOOLKIT_HILDON2
4070         GtkWidget *entry_username = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
4071         if (initial_username)
4072                 hildon_entry_set_text (HILDON_ENTRY (entry_username), initial_username);
4073 #else
4074         GtkWidget *entry_username = gtk_entry_new ();
4075         if (initial_username)
4076                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
4077 #endif
4078         /* Dim this if a connection has ever succeeded with this username,
4079          * as per the UI spec: */
4080         /* const gboolean username_known =  */
4081         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
4082         /*              modest_runtime_get_account_mgr(), server_account_name); */
4083         /* gtk_widget_set_sensitive (entry_username, !username_known); */
4084
4085         /* We drop the username sensitive code and disallow changing it here
4086          * as tinymail does not support really changing the username in the callback
4087          */
4088         gtk_widget_set_sensitive (entry_username, FALSE);
4089
4090 #ifndef MODEST_TOOLKIT_GTK
4091         /* Auto-capitalization is the default, so let's turn it off: */
4092         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
4093
4094         /* Create a size group to be used by all captions.
4095          * Note that HildonCaption does not create a default size group if we do not specify one.
4096          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
4097         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
4098
4099 #ifdef MODEST_TOOLKIT_HILDON2
4100         GtkWidget *caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4101                                                                   _("mail_fi_username"), FALSE,
4102                                                                   entry_username);
4103 #else
4104         GtkWidget *caption = hildon_caption_new (sizegroup,
4105                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
4106 #endif
4107         gtk_widget_show (entry_username);
4108         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4109                 FALSE, FALSE, MODEST_MARGIN_HALF);
4110         gtk_widget_show (caption);
4111 #else
4112         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
4113                             TRUE, FALSE, 0);
4114 #endif /* !MODEST_TOOLKIT_GTK */
4115
4116         /* password: */
4117 #ifdef MODEST_TOOLKIT_HILDON2
4118         GtkWidget *entry_password = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
4119 #else
4120         GtkWidget *entry_password = gtk_entry_new ();
4121 #endif
4122         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
4123         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
4124
4125 #ifndef MODEST_TOOLKIT_GTK
4126         /* Auto-capitalization is the default, so let's turn it off: */
4127         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
4128                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
4129
4130 #ifdef MODEST_TOOLKIT_HILDON2
4131         caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4132                                                        _("mail_fi_password"), FALSE,
4133                                                        entry_password);
4134 #else
4135         caption = hildon_caption_new (sizegroup,
4136                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
4137 #endif
4138         gtk_widget_show (entry_password);
4139         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4140                 FALSE, FALSE, MODEST_MARGIN_HALF);
4141         gtk_widget_show (caption);
4142         g_object_unref (sizegroup);
4143 #else
4144         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
4145                             TRUE, FALSE, 0);
4146 #endif /* !MODEST_TOOLKIT_GTK */
4147
4148         if (initial_username != NULL)
4149                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
4150
4151 /* This is not in the Maemo UI spec:
4152         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
4153         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
4154                             TRUE, FALSE, 0);
4155 */
4156
4157         fields = g_slice_new0 (PasswordDialogFields);
4158         fields->username = entry_username;
4159         fields->password = entry_password;
4160         fields->dialog = dialog;
4161
4162         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
4163         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
4164         password_dialog_check_field (NULL, fields);
4165
4166         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4167
4168         while (!completed) {
4169
4170                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
4171                         if (username) {
4172 #ifdef MODEST_TOOLKIT_HILDON2
4173                                 *username = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_username)));
4174 #else
4175                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
4176 #endif
4177
4178                                 /* Note that an empty field becomes the "" string */
4179                                 if (*username && strlen (*username) > 0) {
4180                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
4181                                                                                         server_account_name,
4182                                                                                         *username);
4183                                         completed = TRUE;
4184
4185                                         const gboolean username_was_changed =
4186                                                 (strcmp (*username, initial_username) != 0);
4187                                         if (username_was_changed) {
4188                                                 g_warning ("%s: tinymail does not yet support changing the "
4189                                                            "username in the get_password() callback.\n", __FUNCTION__);
4190                                         }
4191                                 } else {
4192                                         g_free (*username);
4193                                         *username = NULL;
4194                                         /* Show error */
4195                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
4196                                                                             _("mcen_ib_username_pw_incorrect"));
4197                                         completed = FALSE;
4198                                 }
4199                         }
4200
4201                         if (password) {
4202 #ifdef MODEST_TOOLKIT_HILDON2
4203                                 *password = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_password)));
4204 #else
4205                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
4206 #endif
4207
4208                                 /* We do not save the password in the configuration,
4209                                  * because this function is only called for passwords that should
4210                                  * not be remembered:
4211                                  modest_server_account_set_password (
4212                                  modest_runtime_get_account_mgr(), server_account_name,
4213                                  *password);
4214                                  */
4215                         }
4216                         if (cancel)
4217                                 *cancel   = FALSE;
4218                 } else {
4219 #ifndef MODEST_TOOLKIT_HILDON2
4220                         /* Set parent to NULL or the banner will disappear with its parent dialog */
4221                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
4222 #endif
4223                         completed = TRUE;
4224                         if (username)
4225                                 *username = NULL;
4226                         if (password)
4227                                 *password = NULL;
4228                         if (cancel)
4229                                 *cancel   = TRUE;
4230                 }
4231         }
4232
4233 /* This is not in the Maemo UI spec:
4234         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
4235                 *remember = TRUE;
4236         else
4237                 *remember = FALSE;
4238 */
4239
4240         g_free (initial_username);
4241         gtk_widget_destroy (dialog);
4242         g_slice_free (PasswordDialogFields, fields);
4243
4244         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
4245 }
4246
4247 void
4248 modest_ui_actions_on_cut (GtkAction *action,
4249                           ModestWindow *window)
4250 {
4251         GtkWidget *focused_widget;
4252         GtkClipboard *clipboard;
4253
4254         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4255         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4256         if (GTK_IS_EDITABLE (focused_widget)) {
4257                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
4258                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4259                 gtk_clipboard_store (clipboard);
4260         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4261                 GtkTextBuffer *buffer;
4262
4263                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4264                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4265                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
4266                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4267                         gtk_clipboard_store (clipboard);
4268                 }
4269         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4270                 TnyList *header_list = modest_header_view_get_selected_headers (
4271                                 MODEST_HEADER_VIEW (focused_widget));
4272                 gboolean continue_download = FALSE;
4273                 gint num_of_unc_msgs;
4274
4275                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4276
4277                 if (num_of_unc_msgs) {
4278                         TnyAccount *account = get_account_from_header_list (header_list);
4279                         if (account) {
4280                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4281                                 g_object_unref (account);
4282                         }
4283                 }
4284
4285                 if (num_of_unc_msgs == 0 || continue_download) {
4286 /*                      modest_platform_information_banner (
4287                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
4288                         modest_header_view_cut_selection (
4289                                         MODEST_HEADER_VIEW (focused_widget));
4290                 }
4291
4292                 g_object_unref (header_list);
4293         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4294                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
4295         }
4296 }
4297
4298 void
4299 modest_ui_actions_on_copy (GtkAction *action,
4300                            ModestWindow *window)
4301 {
4302         GtkClipboard *clipboard;
4303         GtkWidget *focused_widget;
4304         gboolean copied = TRUE;
4305
4306         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4307         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4308
4309         if (GTK_IS_LABEL (focused_widget)) {
4310                 gchar *selection;
4311                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
4312                 gtk_clipboard_set_text (clipboard, selection, -1);
4313                 g_free (selection);
4314                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4315                 gtk_clipboard_store (clipboard);
4316         } else if (GTK_IS_EDITABLE (focused_widget)) {
4317                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
4318                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4319                 gtk_clipboard_store (clipboard);
4320         } else if (GTK_IS_HTML (focused_widget)) {
4321                 const gchar *sel;
4322                 int len = -1;
4323                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
4324                 if ((sel == NULL) || (sel[0] == '\0')) {
4325                         copied = FALSE;
4326                 } else {
4327                         gtk_html_copy (GTK_HTML (focused_widget));
4328                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4329                         gtk_clipboard_store (clipboard);
4330                 }
4331         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4332                 GtkTextBuffer *buffer;
4333                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4334                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4335                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
4336                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4337                         gtk_clipboard_store (clipboard);
4338                 }
4339         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4340                 TnyList *header_list = modest_header_view_get_selected_headers (
4341                                 MODEST_HEADER_VIEW (focused_widget));
4342                 gboolean continue_download = FALSE;
4343                 gint num_of_unc_msgs;
4344
4345                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4346
4347                 if (num_of_unc_msgs) {
4348                         TnyAccount *account = get_account_from_header_list (header_list);
4349                         if (account) {
4350                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4351                                 g_object_unref (account);
4352                         }
4353                 }
4354
4355                 if (num_of_unc_msgs == 0 || continue_download) {
4356                         modest_platform_information_banner (
4357                                         NULL, NULL, _CS("mcen_ib_getting_items"));
4358                         modest_header_view_copy_selection (
4359                                         MODEST_HEADER_VIEW (focused_widget));
4360                 } else
4361                         copied = FALSE;
4362
4363                 g_object_unref (header_list);
4364
4365         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4366                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
4367         }
4368
4369         /* Show information banner if there was a copy to clipboard */
4370         if(copied)
4371                 modest_platform_information_banner (
4372                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
4373 }
4374
4375 void
4376 modest_ui_actions_on_undo (GtkAction *action,
4377                            ModestWindow *window)
4378 {
4379         ModestEmailClipboard *clipboard = NULL;
4380
4381         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4382                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
4383         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4384                 /* Clear clipboard source */
4385                 clipboard = modest_runtime_get_email_clipboard ();
4386                 modest_email_clipboard_clear (clipboard);
4387         }
4388         else {
4389                 g_return_if_reached ();
4390         }
4391 }
4392
4393 void
4394 modest_ui_actions_on_redo (GtkAction *action,
4395                            ModestWindow *window)
4396 {
4397         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4398                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
4399         }
4400         else {
4401                 g_return_if_reached ();
4402         }
4403 }
4404
4405
4406 static void
4407 destroy_information_note (ModestMailOperation *mail_op,
4408                           gpointer user_data)
4409 {
4410         /* destroy information note */
4411         gtk_widget_destroy (GTK_WIDGET(user_data));
4412 }
4413
4414 static void
4415 destroy_folder_information_note (ModestMailOperation *mail_op,
4416                                  TnyFolder *new_folder,
4417                                  gpointer user_data)
4418 {
4419         /* destroy information note */
4420         gtk_widget_destroy (GTK_WIDGET(user_data));
4421 }
4422
4423
4424 static void
4425 paste_as_attachment_free (gpointer data)
4426 {
4427         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
4428
4429         if (helper->banner) {
4430                 gtk_widget_destroy (helper->banner);
4431                 g_object_unref (helper->banner);
4432         }
4433         g_free (helper);
4434 }
4435
4436 static void
4437 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
4438                             TnyHeader *header,
4439                             TnyMsg *msg,
4440                             gpointer userdata)
4441 {
4442         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4443         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4444
4445         if (msg == NULL)
4446                 return;
4447
4448         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4449
4450 }
4451
4452 void
4453 modest_ui_actions_on_paste (GtkAction *action,
4454                             ModestWindow *window)
4455 {
4456         GtkWidget *focused_widget = NULL;
4457         GtkWidget *inf_note = NULL;
4458         ModestMailOperation *mail_op = NULL;
4459
4460         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4461         if (GTK_IS_EDITABLE (focused_widget)) {
4462                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4463         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4464                 ModestEmailClipboard *e_clipboard = NULL;
4465                 e_clipboard = modest_runtime_get_email_clipboard ();
4466                 if (modest_email_clipboard_cleared (e_clipboard)) {
4467                         GtkTextBuffer *buffer;
4468                         GtkClipboard *clipboard;
4469
4470                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4471                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4472                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4473                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4474                         ModestMailOperation *mail_op;
4475                         TnyFolder *src_folder = NULL;
4476                         TnyList *data = NULL;
4477                         gboolean delete;
4478                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4479                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4480                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4481                                                                            _CS("ckct_nw_pasting"));
4482                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4483                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4484                         if (helper->banner != NULL) {
4485                                 g_object_ref (G_OBJECT (helper->banner));
4486                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4487                         }
4488
4489                         if (data != NULL) {
4490                                 modest_mail_operation_get_msgs_full (mail_op,
4491                                                                      data,
4492                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4493                                                                      helper,
4494                                                                      paste_as_attachment_free);
4495                         }
4496                         /* Free */
4497                         if (data)
4498                                 g_object_unref (data);
4499                         if (src_folder)
4500                                 g_object_unref (src_folder);
4501
4502                 }
4503         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4504                 ModestEmailClipboard *clipboard = NULL;
4505                 TnyFolder *src_folder = NULL;
4506                 TnyFolderStore *folder_store = NULL;
4507                 TnyList *data = NULL;
4508                 gboolean delete = FALSE;
4509
4510                 /* Check clipboard source */
4511                 clipboard = modest_runtime_get_email_clipboard ();
4512                 if (modest_email_clipboard_cleared (clipboard))
4513                         return;
4514
4515                 /* Get elements to paste */
4516                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4517
4518                 /* Create a new mail operation */
4519                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4520
4521                 /* Get destination folder */
4522                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4523
4524                 /* transfer messages  */
4525                 if (data != NULL) {
4526                         gint response = 0;
4527
4528                         /* Ask for user confirmation */
4529                         response =
4530                                 modest_ui_actions_msgs_move_to_confirmation (window,
4531                                                                              TNY_FOLDER (folder_store),
4532                                                                              delete,
4533                                                                              data);
4534
4535                         if (response == GTK_RESPONSE_OK) {
4536                                 /* Launch notification */
4537                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4538                                                                              _CS("ckct_nw_pasting"));
4539                                 if (inf_note != NULL)  {
4540                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4541                                         gtk_widget_show (GTK_WIDGET(inf_note));
4542                                 }
4543
4544                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4545                                 modest_mail_operation_xfer_msgs (mail_op,
4546                                                                  data,
4547                                                                  TNY_FOLDER (folder_store),
4548                                                                  delete,
4549                                                                  destroy_information_note,
4550                                                                  inf_note);
4551                         } else {
4552                                 g_object_unref (mail_op);
4553                         }
4554
4555                 } else if (src_folder != NULL) {
4556                         /* Launch notification */
4557                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4558                                                                      _CS("ckct_nw_pasting"));
4559                         if (inf_note != NULL)  {
4560                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4561                                 gtk_widget_show (GTK_WIDGET(inf_note));
4562                         }
4563
4564                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4565                         modest_mail_operation_xfer_folder (mail_op,
4566                                                            src_folder,
4567                                                            folder_store,
4568                                                            delete,
4569                                                            destroy_folder_information_note,
4570                                                            inf_note);
4571                 }
4572
4573                 /* Free */
4574                 if (data != NULL)
4575                         g_object_unref (data);
4576                 if (src_folder != NULL)
4577                         g_object_unref (src_folder);
4578                 if (folder_store != NULL)
4579                         g_object_unref (folder_store);
4580         }
4581 }
4582
4583
4584 void
4585 modest_ui_actions_on_select_all (GtkAction *action,
4586                                  ModestWindow *window)
4587 {
4588         GtkWidget *focused_widget;
4589
4590         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4591         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4592                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4593         } else if (GTK_IS_LABEL (focused_widget)) {
4594                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4595         } else if (GTK_IS_EDITABLE (focused_widget)) {
4596                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4597         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4598                 GtkTextBuffer *buffer;
4599                 GtkTextIter start, end;
4600
4601                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4602                 gtk_text_buffer_get_start_iter (buffer, &start);
4603                 gtk_text_buffer_get_end_iter (buffer, &end);
4604                 gtk_text_buffer_select_range (buffer, &start, &end);
4605         } else if (GTK_IS_HTML (focused_widget)) {
4606                 gtk_html_select_all (GTK_HTML (focused_widget));
4607         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4608                 GtkWidget *header_view = focused_widget;
4609                 GtkTreeSelection *selection = NULL;
4610
4611                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4612                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4613                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4614                 }
4615
4616                 /* Disable window dimming management */
4617                 modest_window_disable_dimming (MODEST_WINDOW(window));
4618
4619                 /* Select all messages */
4620                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4621                 gtk_tree_selection_select_all (selection);
4622
4623                 /* Set focuse on header view */
4624                 gtk_widget_grab_focus (header_view);
4625
4626                 /* Enable window dimming management */
4627                 modest_window_enable_dimming (MODEST_WINDOW(window));
4628                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4629                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4630         }
4631
4632 }
4633
4634 void
4635 modest_ui_actions_on_mark_as_read (GtkAction *action,
4636                                    ModestWindow *window)
4637 {
4638         g_return_if_fail (MODEST_IS_WINDOW(window));
4639
4640         /* Mark each header as read */
4641         do_headers_action (window, headers_action_mark_as_read, NULL);
4642 }
4643
4644 void
4645 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4646                                      ModestWindow *window)
4647 {
4648         g_return_if_fail (MODEST_IS_WINDOW(window));
4649
4650         /* Mark each header as read */
4651         do_headers_action (window, headers_action_mark_as_unread, NULL);
4652 }
4653
4654 void
4655 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4656                                   GtkRadioAction *selected,
4657                                   ModestWindow *window)
4658 {
4659         gint value;
4660
4661         value = gtk_radio_action_get_current_value (selected);
4662         if (MODEST_IS_WINDOW (window)) {
4663                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4664         }
4665 }
4666
4667 void
4668 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4669                                                GtkRadioAction *selected,
4670                                                ModestWindow *window)
4671 {
4672         TnyHeaderFlags flags;
4673         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4674
4675         flags = gtk_radio_action_get_current_value (selected);
4676         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4677 }
4678
4679 void
4680 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4681                                                   GtkRadioAction *selected,
4682                                                   ModestWindow *window)
4683 {
4684         gint file_format;
4685
4686         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4687
4688         file_format = gtk_radio_action_get_current_value (selected);
4689         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4690 }
4691
4692
4693 void
4694 modest_ui_actions_on_zoom_plus (GtkAction *action,
4695                                 ModestWindow *window)
4696 {
4697         g_return_if_fail (MODEST_IS_WINDOW (window));
4698
4699         modest_window_zoom_plus (MODEST_WINDOW (window));
4700 }
4701
4702 void
4703 modest_ui_actions_on_zoom_minus (GtkAction *action,
4704                                  ModestWindow *window)
4705 {
4706         g_return_if_fail (MODEST_IS_WINDOW (window));
4707
4708         modest_window_zoom_minus (MODEST_WINDOW (window));
4709 }
4710
4711 void
4712 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4713                                            ModestWindow *window)
4714 {
4715         ModestWindowMgr *mgr;
4716         gboolean fullscreen, active;
4717         g_return_if_fail (MODEST_IS_WINDOW (window));
4718
4719         mgr = modest_runtime_get_window_mgr ();
4720
4721         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4722         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4723
4724         if (active != fullscreen) {
4725                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4726 #ifndef MODEST_TOOLKIT_HILDON2
4727                 gtk_window_present (GTK_WINDOW (window));
4728 #endif
4729         }
4730 }
4731
4732 void
4733 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4734                                         ModestWindow *window)
4735 {
4736         ModestWindowMgr *mgr;
4737         gboolean fullscreen;
4738
4739         g_return_if_fail (MODEST_IS_WINDOW (window));
4740
4741         mgr = modest_runtime_get_window_mgr ();
4742         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4743         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4744
4745 #ifndef MODEST_TOOLKIT_HILDON2
4746         gtk_window_present (GTK_WINDOW (window));
4747 #endif
4748 }
4749
4750 /*
4751  * Used by modest_ui_actions_on_details to call do_headers_action
4752  */
4753 static void
4754 headers_action_show_details (TnyHeader *header,
4755                              ModestWindow *window,
4756                              gpointer user_data)
4757
4758 {
4759         gboolean async_retrieval;
4760         TnyMsg *msg = NULL;
4761
4762         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4763                 async_retrieval = TRUE;
4764                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
4765         } else {
4766                 async_retrieval = FALSE;
4767         }
4768         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
4769         if (msg)
4770                 g_object_unref (msg);
4771 }
4772
4773 /*
4774  * Show the header details in a ModestDetailsDialog widget
4775  */
4776 void
4777 modest_ui_actions_on_details (GtkAction *action,
4778                               ModestWindow *win)
4779 {
4780         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4781                 TnyMsg *msg;
4782                 TnyHeader *header;
4783
4784                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4785                 if (!msg)
4786                         return;
4787
4788                 header = tny_msg_get_header (msg);
4789                 if (header) {
4790                         headers_action_show_details (header, win, NULL);
4791                         g_object_unref (header);
4792                 }
4793                 g_object_unref (msg);
4794
4795         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4796                 GtkWidget *folder_view, *header_view;
4797
4798                 /* Check which widget has the focus */
4799                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4800                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4801                 if (gtk_widget_is_focus (folder_view)) {
4802                         TnyFolderStore *folder_store
4803                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4804                         if (!folder_store) {
4805                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4806                                 return;
4807                         }
4808                         /* Show only when it's a folder */
4809                         /* This function should not be called for account items,
4810                          * because we dim the menu item for them. */
4811                         if (TNY_IS_FOLDER (folder_store)) {
4812                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4813                                                                            TNY_FOLDER (folder_store));
4814                         }
4815
4816                         g_object_unref (folder_store);
4817
4818                 } else {
4819                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4820                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4821                         /* Show details of each header */
4822                         do_headers_action (win, headers_action_show_details, header_view);
4823                 }
4824 #ifdef MODEST_TOOLKIT_HILDON2
4825         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4826                 TnyFolder *folder;
4827                 GtkWidget *header_view;
4828
4829                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4830                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4831                 if (folder) {
4832                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4833                                                                    folder);
4834                         g_object_unref (folder);
4835                 }
4836 #endif
4837         }
4838 }
4839
4840 void
4841 modest_ui_actions_on_limit_error (GtkAction *action,
4842                                   ModestWindow *win)
4843 {
4844         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
4845
4846         modest_platform_information_banner ((GtkWidget *) win, NULL, _CS("ckdg_ib_maximum_characters_reached"));
4847
4848 }
4849
4850 void
4851 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4852                                      ModestMsgEditWindow *window)
4853 {
4854         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4855
4856         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4857 }
4858
4859 void
4860 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4861                                       ModestMsgEditWindow *window)
4862 {
4863         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4864
4865         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4866 }
4867
4868 void
4869 modest_ui_actions_toggle_folders_view (GtkAction *action,
4870                                        ModestMainWindow *main_window)
4871 {
4872         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4873
4874         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4875                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4876         else
4877                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4878 }
4879
4880 void
4881 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4882                                      ModestWindow *window)
4883 {
4884         gboolean active, fullscreen = FALSE;
4885         ModestWindowMgr *mgr;
4886
4887         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4888
4889         /* Check if we want to toggle the toolbar view in fullscreen
4890            or normal mode */
4891         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4892                      "ViewShowToolbarFullScreen")) {
4893                 fullscreen = TRUE;
4894         }
4895
4896         /* Toggle toolbar */
4897         mgr = modest_runtime_get_window_mgr ();
4898         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4899 }
4900
4901 void
4902 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4903                                            ModestMsgEditWindow *window)
4904 {
4905         modest_msg_edit_window_select_font (window);
4906 }
4907
4908
4909 void
4910 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4911                                                   const gchar *display_name,
4912                                                   GtkWindow *window)
4913 {
4914         /* don't update the display name if it was already set;
4915          * updating the display name apparently is expensive */
4916         const gchar* old_name = gtk_window_get_title (window);
4917
4918         if (display_name == NULL)
4919                 display_name = " ";
4920
4921         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4922                 return; /* don't do anything */
4923
4924         /* This is usually used to change the title of the main window, which
4925          * is the one that holds the folder view. Note that this change can
4926          * happen even when the widget doesn't have the focus. */
4927         gtk_window_set_title (window, display_name);
4928
4929 }
4930
4931 void
4932 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4933 {
4934         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4935         modest_msg_edit_window_select_contacts (window);
4936 }
4937
4938 void
4939 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4940 {
4941         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4942         modest_msg_edit_window_check_names (window, FALSE);
4943 }
4944
4945 #ifndef MODEST_TOOLKIT_HILDON2
4946 /*
4947  * This function is used to track changes in the selection of the
4948  * folder view that is inside the "move to" dialog to enable/disable
4949  * the OK button because we do not want the user to select a disallowed
4950  * destination for a folder.
4951  * The user also not desired to be able to use NEW button on items where
4952  * folder creation is not possibel.
4953  */
4954 static void
4955 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4956                                             TnyFolderStore *folder_store,
4957                                             gboolean selected,
4958                                             gpointer user_data)
4959 {
4960         GtkWidget *dialog = NULL;
4961         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4962         gboolean moving_folder = FALSE;
4963         gboolean is_local_account = TRUE;
4964         GtkWidget *folder_view = NULL;
4965         ModestTnyFolderRules rules;
4966
4967         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4968
4969         if (!selected)
4970                 return;
4971
4972         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4973         if (!dialog)
4974                 return;
4975
4976         /* check if folder_store is an remote account */
4977         if (TNY_IS_ACCOUNT (folder_store)) {
4978                 TnyAccount *local_account = NULL;
4979                 TnyAccount *mmc_account = NULL;
4980                 ModestTnyAccountStore *account_store = NULL;
4981
4982                 account_store = modest_runtime_get_account_store ();
4983                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4984                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4985
4986                 if ((gpointer) local_account != (gpointer) folder_store &&
4987                     (gpointer) mmc_account != (gpointer) folder_store) {
4988                         ModestProtocolType proto;
4989                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
4990                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
4991                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
4992                         }
4993                         is_local_account = FALSE;
4994                         /* New button should be dimmed on remote
4995                            POP account root */
4996                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4997                                                                                          proto,
4998                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
4999                 }
5000                 g_object_unref (local_account);
5001
5002                 /* It could not exist */
5003                 if (mmc_account)
5004                         g_object_unref (mmc_account);
5005         }
5006
5007         /* Check the target folder rules */
5008         if (TNY_IS_FOLDER (folder_store)) {
5009                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
5010                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
5011                         ok_sensitive = FALSE;
5012                         new_sensitive = FALSE;
5013                         goto end;
5014                 }
5015         }
5016
5017         /* Check if we're moving a folder */
5018         if (MODEST_IS_MAIN_WINDOW (user_data)) {
5019                 /* Get the widgets */
5020                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
5021                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5022                 if (gtk_widget_is_focus (folder_view))
5023                         moving_folder = TRUE;
5024         }
5025
5026         if (moving_folder) {
5027                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
5028
5029                 /* Get the folder to move */
5030                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5031
5032                 /* Check that we're not moving to the same folder */
5033                 if (TNY_IS_FOLDER (moved_folder)) {
5034                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
5035                         if (parent == folder_store)
5036                                 ok_sensitive = FALSE;
5037                         g_object_unref (parent);
5038                 }
5039
5040                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
5041                         /* Do not allow to move to an account unless it's the
5042                            local folders account */
5043                         if (!is_local_account)
5044                                 ok_sensitive = FALSE;
5045                 }
5046
5047                 if (ok_sensitive && (moved_folder == folder_store)) {
5048                         /* Do not allow to move to itself */
5049                         ok_sensitive = FALSE;
5050                 }
5051                 g_object_unref (moved_folder);
5052         } else {
5053                 TnyFolder *src_folder = NULL;
5054
5055                 /* Moving a message */
5056                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
5057
5058                         TnyHeader *header = NULL;
5059                         header = modest_msg_view_window_get_header
5060                                 (MODEST_MSG_VIEW_WINDOW (user_data));
5061                         if (!TNY_IS_HEADER(header))
5062                                 g_warning ("%s: could not get source header", __FUNCTION__);
5063                         else
5064                                 src_folder = tny_header_get_folder (header);
5065
5066                         if (header)
5067                                 g_object_unref (header);
5068                 } else {
5069                         src_folder =
5070                                 TNY_FOLDER (modest_folder_view_get_selected
5071                                             (MODEST_FOLDER_VIEW (folder_view)));
5072                 }
5073
5074                 if (TNY_IS_FOLDER(src_folder)) {
5075                         /* Do not allow to move the msg to the same folder */
5076                         /* Do not allow to move the msg to an account */
5077                         if ((gpointer) src_folder == (gpointer) folder_store ||
5078                             TNY_IS_ACCOUNT (folder_store))
5079                                 ok_sensitive = FALSE;
5080                         g_object_unref (src_folder);
5081                 } else
5082                         g_warning ("%s: could not get source folder", __FUNCTION__);
5083         }
5084
5085  end:
5086         /* Set sensitivity of the OK and NEW button */
5087         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
5088         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
5089 }
5090 #endif
5091
5092 static void
5093 on_move_to_dialog_response (GtkDialog *dialog,
5094                             gint       response,
5095                             gpointer   user_data)
5096 {
5097         GtkWidget *parent_win;
5098         MoveToInfo *helper = NULL;
5099         ModestFolderView *folder_view;
5100         gboolean unset_edit_mode = FALSE;
5101
5102         helper = (MoveToInfo *) user_data;
5103
5104         parent_win = (GtkWidget *) helper->win;
5105         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
5106                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
5107         switch (response) {
5108                 TnyFolderStore *dst_folder;
5109                 TnyFolderStore *selected;
5110
5111         case MODEST_GTK_RESPONSE_NEW_FOLDER:
5112                 selected = modest_folder_view_get_selected (folder_view);
5113                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view), selected);
5114                 g_object_unref (selected);
5115                 return;
5116         case GTK_RESPONSE_NONE:
5117         case GTK_RESPONSE_CANCEL:
5118         case GTK_RESPONSE_DELETE_EVENT:
5119                 break;
5120         case GTK_RESPONSE_OK:
5121                 dst_folder = modest_folder_view_get_selected (folder_view);
5122
5123                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
5124                         /* Clean list to move used for filtering */
5125                         modest_folder_view_set_list_to_move (folder_view, NULL);
5126
5127                         modest_ui_actions_on_main_window_move_to (NULL,
5128                                                                   GTK_WIDGET (folder_view),
5129                                                                   dst_folder,
5130                                                                   MODEST_MAIN_WINDOW (parent_win));
5131 #ifdef MODEST_TOOLKIT_HILDON2
5132                 } else if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
5133                         /* Clean list to move used for filtering */
5134                         modest_folder_view_set_list_to_move (folder_view, NULL);
5135
5136                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
5137                                                                     dst_folder,
5138                                                                     helper->list,
5139                                                                     GTK_WINDOW (parent_win));
5140 #endif
5141                 } else {
5142                         /* if the user selected a root folder
5143                            (account) then do not perform any action */
5144                         if (TNY_IS_ACCOUNT (dst_folder)) {
5145                                 g_signal_stop_emission_by_name (dialog, "response");
5146                                 return;
5147                         }
5148
5149                         /* Clean list to move used for filtering */
5150                         modest_folder_view_set_list_to_move (folder_view, NULL);
5151
5152                         /* Moving from headers window in edit mode */
5153                         modest_ui_actions_on_window_move_to (NULL, helper->list,
5154                                                              dst_folder,
5155                                                              MODEST_WINDOW (parent_win));
5156                 }
5157
5158                 if (dst_folder)
5159                         g_object_unref (dst_folder);
5160
5161                 unset_edit_mode = TRUE;
5162                 break;
5163         default:
5164                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
5165         }
5166
5167         /* Free the helper and exit */
5168         if (helper->list)
5169                 g_object_unref (helper->list);
5170         if (unset_edit_mode) {
5171 #ifdef MODEST_TOOLKIT_HILDON2
5172                 modest_hildon2_window_unset_edit_mode (MODEST_HILDON2_WINDOW (helper->win));
5173 #endif
5174         }
5175         g_slice_free (MoveToInfo, helper);
5176         gtk_widget_destroy (GTK_WIDGET (dialog));
5177 }
5178
5179 static GtkWidget*
5180 create_move_to_dialog (GtkWindow *win,
5181                        GtkWidget *folder_view,
5182                        TnyList *list_to_move)
5183 {
5184         GtkWidget *dialog, *tree_view = NULL;
5185
5186         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
5187
5188 #ifndef MODEST_TOOLKIT_HILDON2
5189         /* Track changes in the selection to
5190          * disable the OK button whenever "Move to" is not possible
5191          * disbale NEW button whenever New is not possible */
5192         g_signal_connect (tree_view,
5193                           "folder_selection_changed",
5194                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
5195                           win);
5196 #endif
5197
5198         /* It could happen that we're trying to move a message from a
5199            window (msg window for example) after the main window was
5200            closed, so we can not just get the model of the folder
5201            view */
5202         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
5203                 const gchar *visible_id = NULL;
5204
5205                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5206                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5207                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
5208                                                MODEST_FOLDER_VIEW(tree_view));
5209
5210                 visible_id =
5211                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
5212
5213                 /* Show the same account than the one that is shown in the main window */
5214                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
5215                                                                              visible_id);
5216         } else {
5217                 const gchar *active_account_name = NULL;
5218                 ModestAccountMgr *mgr = NULL;
5219                 ModestAccountSettings *settings = NULL;
5220                 ModestServerAccountSettings *store_settings = NULL;
5221
5222                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5223                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5224                 /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view), */
5225                 /*                               TNY_ACCOUNT_STORE (modest_runtime_get_account_store ())); */
5226
5227                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
5228                 mgr = modest_runtime_get_account_mgr ();
5229                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
5230
5231                 if (settings) {
5232                         const gchar *store_account_name;
5233                         store_settings = modest_account_settings_get_store_settings (settings);
5234                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
5235
5236                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
5237                                                                                      store_account_name);
5238                         g_object_unref (store_settings);
5239                         g_object_unref (settings);
5240                 }
5241         }
5242
5243         /* we keep a pointer to the embedded folder view, so we can
5244          *   retrieve it with get_folder_view_from_move_to_dialog (see
5245          *   above) later (needed for focus handling)
5246          */
5247         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
5248
5249         /* Hide special folders */
5250 #ifndef MODEST_TOOLKIT_HILDON2
5251         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
5252 #endif
5253         if (list_to_move)
5254                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
5255 #ifndef MODEST_TOOLKIT_HILDON2
5256         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5257 #endif
5258
5259         gtk_widget_show (GTK_WIDGET (tree_view));
5260
5261         return dialog;
5262 }
5263
5264 /*
5265  * Shows a confirmation dialog to the user when we're moving messages
5266  * from a remote server to the local storage. Returns the dialog
5267  * response. If it's other kind of movement then it always returns
5268  * GTK_RESPONSE_OK
5269  *
5270  * This one is used by the next functions:
5271  *      modest_ui_actions_on_paste                      - commented out
5272  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
5273  */
5274 gint
5275 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
5276                                              TnyFolder *dest_folder,
5277                                              gboolean delete,
5278                                              TnyList *headers)
5279 {
5280         gint response = GTK_RESPONSE_OK;
5281         TnyAccount *account = NULL;
5282         TnyFolder *src_folder = NULL;
5283         TnyIterator *iter = NULL;
5284         TnyHeader *header = NULL;
5285
5286         /* return with OK if the destination is a remote folder */
5287         if (modest_tny_folder_is_remote_folder (dest_folder))
5288                 return GTK_RESPONSE_OK;
5289
5290         /* Get source folder */
5291         iter = tny_list_create_iterator (headers);
5292         header = TNY_HEADER (tny_iterator_get_current (iter));
5293         if (header) {
5294                 src_folder = tny_header_get_folder (header);
5295                 g_object_unref (header);
5296         }
5297         g_object_unref (iter);
5298
5299         /* if no src_folder, message may be an attahcment */
5300         if (src_folder == NULL)
5301                 return GTK_RESPONSE_CANCEL;
5302
5303         /* If the source is a local or MMC folder */
5304         if (!modest_tny_folder_is_remote_folder (src_folder)) {
5305                 g_object_unref (src_folder);
5306                 return GTK_RESPONSE_OK;
5307         }
5308
5309         /* Get the account */
5310         account = tny_folder_get_account (src_folder);
5311
5312         /* now if offline we ask the user */
5313         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
5314                 response = GTK_RESPONSE_OK;
5315         else
5316                 response = GTK_RESPONSE_CANCEL;
5317
5318         /* Frees */
5319         g_object_unref (src_folder);
5320         g_object_unref (account);
5321
5322         return response;
5323 }
5324
5325 static void
5326 move_to_helper_destroyer (gpointer user_data)
5327 {
5328         MoveToHelper *helper = (MoveToHelper *) user_data;
5329
5330         /* Close the "Pasting" information banner */
5331         if (helper->banner) {
5332                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
5333                 g_object_unref (helper->banner);
5334         }
5335         if (gtk_tree_row_reference_valid (helper->reference)) {
5336                 gtk_tree_row_reference_free (helper->reference);
5337                 helper->reference = NULL;
5338         }
5339         g_free (helper);
5340 }
5341
5342 static void
5343 move_to_cb (ModestMailOperation *mail_op,
5344             gpointer user_data)
5345 {
5346         MoveToHelper *helper = (MoveToHelper *) user_data;
5347         GObject *object = modest_mail_operation_get_source (mail_op);
5348
5349         /* Note that the operation could have failed, in that case do
5350            nothing */
5351         if (modest_mail_operation_get_status (mail_op) !=
5352             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5353                 goto frees;
5354
5355         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
5356                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
5357
5358                 if (!modest_msg_view_window_select_next_message (self) &&
5359                     !modest_msg_view_window_select_previous_message (self)) {
5360                         /* No more messages to view, so close this window */
5361                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
5362                 }
5363         } else if (MODEST_IS_MAIN_WINDOW (object) &&
5364                    gtk_tree_row_reference_valid (helper->reference)) {
5365                 GtkWidget *header_view;
5366                 GtkTreePath *path;
5367                 GtkTreeSelection *sel;
5368
5369                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5370                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5371                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
5372                 path = gtk_tree_row_reference_get_path (helper->reference);
5373                 /* We need to unselect the previous one
5374                    because we could be copying instead of
5375                    moving */
5376                 gtk_tree_selection_unselect_all (sel);
5377                 gtk_tree_selection_select_path (sel, path);
5378                 gtk_tree_path_free (path);
5379         }
5380         g_object_unref (object);
5381
5382  frees:
5383         /* Destroy the helper */
5384         move_to_helper_destroyer (helper);
5385 }
5386
5387 static void
5388 folder_move_to_cb (ModestMailOperation *mail_op,
5389                    TnyFolder *new_folder,
5390                    gpointer user_data)
5391 {
5392         GtkWidget *folder_view;
5393         GObject *object;
5394
5395         object = modest_mail_operation_get_source (mail_op);
5396         if (MODEST_IS_MAIN_WINDOW (object)) {
5397                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5398                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5399                 g_object_ref (folder_view);
5400                 g_object_unref (object);
5401                 move_to_cb (mail_op, user_data);
5402                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5403                 g_object_unref (folder_view);
5404         } else {
5405                 move_to_cb (mail_op, user_data);
5406         }
5407 }
5408
5409 static void
5410 msgs_move_to_cb (ModestMailOperation *mail_op,
5411                  gpointer user_data)
5412 {
5413         move_to_cb (mail_op, user_data);
5414 }
5415
5416 void
5417 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
5418                                              gpointer user_data)
5419 {
5420         GObject *win = NULL;
5421         const GError *error;
5422         TnyAccount *account = NULL;
5423
5424 #ifndef MODEST_TOOLKIT_HILDON2
5425         ModestWindow *main_window = NULL;
5426
5427         /* Disable next automatic folder selection */
5428         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5429                                                          FALSE); /* don't create */
5430
5431         /* Show notification dialog only if the main window exists */
5432         if (main_window) {
5433                 GtkWidget *folder_view = NULL;
5434
5435                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5436                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5437                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5438
5439                 if (user_data && TNY_IS_FOLDER (user_data)) {
5440                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
5441                                                           TNY_FOLDER (user_data), FALSE);
5442                 }
5443         }
5444 #endif
5445         win = modest_mail_operation_get_source (mail_op);
5446         error = modest_mail_operation_get_error (mail_op);
5447
5448         if (TNY_IS_FOLDER (user_data))
5449                 account = modest_tny_folder_get_account (TNY_FOLDER (user_data));
5450         else if (TNY_IS_ACCOUNT (user_data))
5451                 account = g_object_ref (user_data);
5452
5453         /* If it's not a disk full error then show a generic error */
5454         if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5455                                                              (GtkWidget *) win, (GError *) error,
5456                                                              account, NULL))
5457                 modest_platform_run_information_dialog ((GtkWindow *) win,
5458                                                         _("mail_in_ui_folder_move_target_error"),
5459                                                         FALSE);
5460         if (account)
5461                 g_object_unref (account);
5462         if (win)
5463                 g_object_unref (win);
5464 }
5465
5466 static void
5467 open_msg_for_purge_cb (ModestMailOperation *mail_op,
5468                        TnyHeader *header,
5469                        gboolean canceled,
5470                        TnyMsg *msg,
5471                        GError *err,
5472                        gpointer user_data)
5473 {
5474         TnyList *parts;
5475         TnyIterator *iter;
5476         gint pending_purges = 0;
5477         gboolean some_purged = FALSE;
5478         ModestWindow *win = MODEST_WINDOW (user_data);
5479         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5480
5481         /* If there was any error */
5482         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5483                 modest_window_mgr_unregister_header (mgr, header);
5484                 return;
5485         }
5486
5487         /* Once the message has been retrieved for purging, we check if
5488          * it's all ok for purging */
5489
5490         parts = tny_simple_list_new ();
5491         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5492         iter = tny_list_create_iterator (parts);
5493
5494         while (!tny_iterator_is_done (iter)) {
5495                 TnyMimePart *part;
5496                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5497                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5498                         if (tny_mime_part_is_purged (part))
5499                                 some_purged = TRUE;
5500                         else
5501                                 pending_purges++;
5502                 }
5503
5504                 if (part)
5505                         g_object_unref (part);
5506
5507                 tny_iterator_next (iter);
5508         }
5509         g_object_unref (iter);
5510
5511
5512         if (pending_purges>0) {
5513                 gint response;
5514                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5515
5516                 if (response == GTK_RESPONSE_OK) {
5517                         GtkWidget *info;
5518                         info =
5519                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5520                         iter = tny_list_create_iterator (parts);
5521                         while (!tny_iterator_is_done (iter)) {
5522                                 TnyMimePart *part;
5523
5524                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5525                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5526                                         tny_mime_part_set_purged (part);
5527
5528                                 if (part)
5529                                         g_object_unref (part);
5530
5531                                 tny_iterator_next (iter);
5532                         }
5533                         g_object_unref (iter);
5534
5535                         tny_msg_rewrite_cache (msg);
5536
5537                         gtk_widget_destroy (info);
5538                 }
5539         }
5540
5541         modest_window_mgr_unregister_header (mgr, header);
5542
5543         g_object_unref (parts);
5544 }
5545
5546 static void
5547 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5548                                                      ModestMainWindow *win)
5549 {
5550         GtkWidget *header_view;
5551         TnyList *header_list;
5552         TnyHeader *header;
5553         TnyHeaderFlags flags;
5554         ModestWindow *msg_view_window =  NULL;
5555         gboolean found;
5556
5557         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5558
5559         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5560                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5561
5562         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5563         if (!header_list) {
5564                 g_warning ("%s: no header selected", __FUNCTION__);
5565                 return;
5566         }
5567
5568         if (tny_list_get_length (header_list) == 1) {
5569                 TnyIterator *iter = tny_list_create_iterator (header_list);
5570                 header = TNY_HEADER (tny_iterator_get_current (iter));
5571                 g_object_unref (iter);
5572         } else
5573                 return;
5574
5575         if (!header || !TNY_IS_HEADER(header)) {
5576                 g_warning ("%s: header is not valid", __FUNCTION__);
5577                 return;
5578         }
5579
5580         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5581                                                           header, &msg_view_window);
5582         flags = tny_header_get_flags (header);
5583         if (!(flags & TNY_HEADER_FLAG_CACHED))
5584                 return;
5585         if (found) {
5586                 if (msg_view_window != NULL)
5587                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5588                 else {
5589                         /* do nothing; uid was registered before, so window is probably on it's way */
5590                         g_debug ("header %p has already been registered", header);
5591                 }
5592         } else {
5593                 ModestMailOperation *mail_op = NULL;
5594                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5595                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5596                                                                          modest_ui_actions_disk_operations_error_handler,
5597                                                                          NULL, NULL);
5598                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5599                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5600
5601                 g_object_unref (mail_op);
5602         }
5603         if (header)
5604                 g_object_unref (header);
5605         if (header_list)
5606                 g_object_unref (header_list);
5607 }
5608
5609 /*
5610  * Checks if we need a connection to do the transfer and if the user
5611  * wants to connect to complete it
5612  */
5613 static void
5614 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5615                                        TnyFolderStore *src_folder,
5616                                        TnyList *headers,
5617                                        TnyFolder *dst_folder,
5618                                        gboolean delete_originals,
5619                                        gboolean *need_connection,
5620                                        gboolean *do_xfer)
5621 {
5622         TnyAccount *src_account;
5623         gint uncached_msgs = 0;
5624
5625         /* We don't need any further check if
5626          *
5627          * 1- the source folder is local OR
5628          * 2- the device is already online
5629          */
5630         if (!modest_tny_folder_store_is_remote (src_folder) ||
5631             tny_device_is_online (modest_runtime_get_device())) {
5632                 *need_connection = FALSE;
5633                 *do_xfer = TRUE;
5634                 return;
5635         }
5636
5637         /* We must ask for a connection when
5638          *
5639          *   - the message(s) is not already cached   OR
5640          *   - the message(s) is cached but the leave_on_server setting
5641          * is FALSE (because we need to sync the source folder to
5642          * delete the message from the server (for IMAP we could do it
5643          * offline, it'll take place the next time we get a
5644          * connection)
5645          */
5646         uncached_msgs = header_list_count_uncached_msgs (headers);
5647         src_account = get_account_from_folder_store (src_folder);
5648         if (uncached_msgs > 0) {
5649                 guint num_headers;
5650                 const gchar *msg;
5651
5652                 *need_connection = TRUE;
5653                 num_headers = tny_list_get_length (headers);
5654                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5655
5656                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5657                     GTK_RESPONSE_CANCEL) {
5658                         *do_xfer = FALSE;
5659                 } else {
5660                         *do_xfer = TRUE;
5661                 }
5662         } else {
5663                 /* The transfer is possible and the user wants to */
5664                 *do_xfer = TRUE;
5665
5666                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5667                         const gchar *account_name;
5668                         gboolean leave_on_server;
5669
5670                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5671                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5672                                                                                   account_name);
5673
5674                         if (leave_on_server == TRUE) {
5675                                 *need_connection = FALSE;
5676                         } else {
5677                                 *need_connection = TRUE;
5678                         }
5679                 } else {
5680                         *need_connection = FALSE;
5681                 }
5682         }
5683
5684         /* Frees */
5685         g_object_unref (src_account);
5686 }
5687
5688 static void
5689 xfer_messages_error_handler (ModestMailOperation *mail_op,
5690                              gpointer user_data)
5691 {
5692         GObject *win;
5693         const GError *error;
5694         TnyAccount *account;
5695
5696         win = modest_mail_operation_get_source (mail_op);
5697         error = modest_mail_operation_get_error (mail_op);
5698
5699         /* We cannot get the account from the mail op as that is the
5700            source account and for checking memory full conditions we
5701            need the destination one */
5702         account = TNY_ACCOUNT (user_data);
5703
5704         if (error &&
5705             !modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5706                                                              (GtkWidget *) win, (GError*) error,
5707                                                              account, _KR("cerm_memory_card_full"))) {
5708                 modest_platform_run_information_dialog ((GtkWindow *) win,
5709                                                         _("mail_in_ui_folder_move_target_error"),
5710                                                         FALSE);
5711         }
5712         if (win)
5713                 g_object_unref (win);
5714 }
5715
5716 typedef struct {
5717         TnyFolderStore *dst_folder;
5718         TnyList *headers;
5719 } XferMsgsHelper;
5720
5721 /**
5722  * Utility function that transfer messages from both the main window
5723  * and the msg view window when using the "Move to" dialog
5724  */
5725 static void
5726 xfer_messages_performer  (gboolean canceled,
5727                           GError *err,
5728                           GtkWindow *parent_window,
5729                           TnyAccount *account,
5730                           gpointer user_data)
5731 {
5732         ModestWindow *win = MODEST_WINDOW (parent_window);
5733         TnyAccount *dst_account = NULL;
5734         gboolean dst_forbids_message_add = FALSE;
5735         XferMsgsHelper *helper;
5736         MoveToHelper *movehelper;
5737         ModestMailOperation *mail_op;
5738
5739         helper = (XferMsgsHelper *) user_data;
5740
5741         if (canceled || err) {
5742                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5743                                                                      (GtkWidget *) parent_window, err,
5744                                                                      account, NULL)) {
5745                         /* Show the proper error message */
5746                         modest_ui_actions_on_account_connection_error (parent_window, account);
5747                 }
5748                 goto end;
5749         }
5750
5751         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5752
5753         /* tinymail will return NULL for local folders it seems */
5754         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5755                                                                                   modest_tny_account_get_protocol_type (dst_account),
5756                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
5757
5758         if (dst_forbids_message_add) {
5759                 modest_platform_information_banner (GTK_WIDGET (win),
5760                                                     NULL,
5761                                                     ngettext("mail_in_ui_folder_move_target_error",
5762                                                              "mail_in_ui_folder_move_targets_error",
5763                                                              tny_list_get_length (helper->headers)));
5764                 goto end;
5765         }
5766
5767         movehelper = g_new0 (MoveToHelper, 1);
5768
5769 #ifndef MODEST_TOOLKIT_HILDON2
5770         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5771                                                                _CS("ckct_nw_pasting"));
5772         if (movehelper->banner != NULL)  {
5773                 g_object_ref (movehelper->banner);
5774                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5775         }
5776 #endif
5777
5778         if (MODEST_IS_MAIN_WINDOW (win)) {
5779                 GtkWidget *header_view =
5780                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5781                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5782                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5783         }
5784
5785         /* Perform the mail operation */
5786         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5787                                                                  xfer_messages_error_handler,
5788                                                                  g_object_ref (dst_account),
5789                                                                  g_object_unref);
5790         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5791                                          mail_op);
5792
5793         modest_mail_operation_xfer_msgs (mail_op,
5794                                          helper->headers,
5795                                          TNY_FOLDER (helper->dst_folder),
5796                                          TRUE,
5797                                          msgs_move_to_cb,
5798                                          movehelper);
5799
5800         g_object_unref (G_OBJECT (mail_op));
5801  end:
5802         if (dst_account)
5803                 g_object_unref (dst_account);
5804         g_object_unref (helper->dst_folder);
5805         g_object_unref (helper->headers);
5806         g_slice_free (XferMsgsHelper, helper);
5807 }
5808
5809 typedef struct {
5810         TnyFolder *src_folder;
5811         TnyFolderStore *dst_folder;
5812         gboolean delete_original;
5813         GtkWidget *folder_view;
5814 } MoveFolderInfo;
5815
5816 static void
5817 on_move_folder_cb (gboolean canceled,
5818                    GError *err,
5819                    GtkWindow *parent_window,
5820                    TnyAccount *account,
5821                    gpointer user_data)
5822 {
5823         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5824         GtkTreeSelection *sel;
5825         ModestMailOperation *mail_op = NULL;
5826
5827         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
5828                 /* Note that the connection process can fail due to
5829                    memory low conditions as it can not successfully
5830                    store the summary */
5831                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5832                                                                      (GtkWidget*) parent_window, err,
5833                                                                      account, NULL))
5834                         g_debug ("Error connecting when trying to move a folder");
5835
5836                 g_object_unref (G_OBJECT (info->src_folder));
5837                 g_object_unref (G_OBJECT (info->dst_folder));
5838                 g_free (info);
5839                 return;
5840         }
5841
5842         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5843 #ifndef MODEST_TOOLKIT_HILDON2
5844         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5845                         _CS("ckct_nw_pasting"));
5846         if (helper->banner != NULL)  {
5847                 g_object_ref (helper->banner);
5848                 gtk_widget_show (GTK_WIDGET(helper->banner));
5849         }
5850 #endif
5851         /* Clean folder on header view before moving it */
5852         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5853         gtk_tree_selection_unselect_all (sel);
5854
5855         /* Let gtk events run. We need that the folder
5856            view frees its reference to the source
5857            folder *before* issuing the mail operation
5858            so we need the signal handler of selection
5859            changed to happen before the mail
5860            operation
5861         while (gtk_events_pending ())
5862                 gtk_main_iteration ();   */
5863
5864         mail_op =
5865                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5866                                                                modest_ui_actions_move_folder_error_handler,
5867                                                                g_object_ref (info->dst_folder), g_object_unref);
5868         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5869                                          mail_op);
5870
5871         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
5872                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5873                                                   TNY_FOLDER (info->dst_folder), TRUE);
5874         }
5875         modest_mail_operation_xfer_folder (mail_op,
5876                         TNY_FOLDER (info->src_folder),
5877                         info->dst_folder,
5878                         info->delete_original,
5879                         folder_move_to_cb,
5880                         helper);
5881         g_object_unref (G_OBJECT (info->src_folder));
5882
5883         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5884         /* } */
5885
5886         /* Unref mail operation */
5887         g_object_unref (G_OBJECT (mail_op));
5888         g_object_unref (G_OBJECT (info->dst_folder));
5889         g_free (user_data);
5890 }
5891
5892 static TnyAccount *
5893 get_account_from_folder_store (TnyFolderStore *folder_store)
5894 {
5895         if (TNY_IS_ACCOUNT (folder_store))
5896                 return g_object_ref (folder_store);
5897         else
5898                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5899 }
5900
5901 /*
5902  * UI handler for the "Move to" action when invoked from the
5903  * ModestMainWindow
5904  */
5905 static void
5906 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5907                                           GtkWidget *folder_view,
5908                                           TnyFolderStore *dst_folder,
5909                                           ModestMainWindow *win)
5910 {
5911         ModestHeaderView *header_view = NULL;
5912         TnyFolderStore *src_folder = NULL;
5913
5914         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5915
5916         /* Get the source folder */
5917         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5918
5919         /* Get header view */
5920         header_view = (ModestHeaderView *)
5921                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5922
5923         /* Get folder or messages to transfer */
5924         if (gtk_widget_is_focus (folder_view)) {
5925                 gboolean do_xfer = TRUE;
5926
5927                 /* Allow only to transfer folders to the local root folder */
5928                 if (TNY_IS_ACCOUNT (dst_folder) &&
5929                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5930                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5931                         do_xfer = FALSE;
5932                 } else if (!TNY_IS_FOLDER (src_folder)) {
5933                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5934                         do_xfer = FALSE;
5935                 }
5936
5937                 if (do_xfer) {
5938                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5939                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5940
5941                         info->src_folder = g_object_ref (src_folder);
5942                         info->dst_folder = g_object_ref (dst_folder);
5943                         info->delete_original = TRUE;
5944                         info->folder_view = folder_view;
5945
5946                         connect_info->callback = on_move_folder_cb;
5947                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5948                         connect_info->data = info;
5949
5950                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5951                                                                    TNY_FOLDER_STORE (src_folder),
5952                                                                    connect_info);
5953                 }
5954         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5955                 TnyList *headers;
5956
5957                 headers = modest_header_view_get_selected_headers(header_view);
5958
5959                 /* Transfer the messages */
5960                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
5961                                                             headers, TNY_FOLDER (dst_folder));
5962
5963                 g_object_unref (headers);
5964         }
5965
5966         /* Frees */
5967         g_object_unref (src_folder);
5968 }
5969
5970 #ifdef MODEST_TOOLKIT_HILDON2
5971 /*
5972  * UI handler for the "Move to" action when invoked from the
5973  * ModestFolderWindow
5974  */
5975 static void
5976 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
5977                                             TnyFolderStore *dst_folder,
5978                                             TnyList *selection,
5979                                             GtkWindow *win)
5980 {
5981         TnyFolderStore *src_folder = NULL;
5982         TnyIterator *iterator;
5983
5984         if (tny_list_get_length (selection) != 1)
5985                 return;
5986
5987         iterator = tny_list_create_iterator (selection);
5988         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
5989         g_object_unref (iterator);
5990
5991
5992         gboolean do_xfer = TRUE;
5993
5994         /* Allow only to transfer folders to the local root folder */
5995         if (TNY_IS_ACCOUNT (dst_folder) &&
5996             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5997             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5998                 do_xfer = FALSE;
5999                 /* Show an error */
6000                 modest_platform_run_information_dialog (win,
6001                                                         _("mail_in_ui_folder_move_target_error"),
6002                                                         FALSE);
6003         } else if (!TNY_IS_FOLDER (src_folder)) {
6004                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
6005                 do_xfer = FALSE;
6006         }
6007
6008         if (do_xfer) {
6009                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
6010                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6011
6012                 info->src_folder = g_object_ref (src_folder);
6013                 info->dst_folder = g_object_ref (dst_folder);
6014                 info->delete_original = TRUE;
6015                 info->folder_view = folder_view;
6016
6017                 connect_info->callback = on_move_folder_cb;
6018                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
6019                 connect_info->data = info;
6020
6021                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6022                                                            TNY_FOLDER_STORE (src_folder),
6023                                                            connect_info);
6024         }
6025
6026         /* Frees */
6027         g_object_unref (src_folder);
6028 }
6029 #endif
6030
6031
6032 void
6033 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
6034                                             TnyFolder *src_folder,
6035                                             TnyList *headers,
6036                                             TnyFolder *dst_folder)
6037 {
6038         gboolean need_connection = TRUE;
6039         gboolean do_xfer = TRUE;
6040         XferMsgsHelper *helper;
6041
6042         g_return_if_fail (TNY_IS_FOLDER (src_folder));
6043         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6044         g_return_if_fail (TNY_IS_LIST (headers));
6045
6046         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
6047                                                headers, TNY_FOLDER (dst_folder),
6048                                                TRUE, &need_connection,
6049                                                &do_xfer);
6050
6051         /* If we don't want to transfer just return */
6052         if (!do_xfer)
6053                 return;
6054
6055         /* Create the helper */
6056         helper = g_slice_new (XferMsgsHelper);
6057         helper->dst_folder = g_object_ref (dst_folder);
6058         helper->headers = g_object_ref (headers);
6059
6060         if (need_connection) {
6061                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6062                 connect_info->callback = xfer_messages_performer;
6063                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
6064                 connect_info->data = helper;
6065
6066                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6067                                                            TNY_FOLDER_STORE (src_folder),
6068                                                            connect_info);
6069         } else {
6070                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
6071                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
6072                                          src_account, helper);
6073                 g_object_unref (src_account);
6074         }
6075 }
6076
6077 /*
6078  * UI handler for the "Move to" action when invoked from the
6079  * ModestMsgViewWindow
6080  */
6081 static void
6082 modest_ui_actions_on_window_move_to (GtkAction *action,
6083                                      TnyList *headers,
6084                                      TnyFolderStore *dst_folder,
6085                                      ModestWindow *win)
6086 {
6087         TnyFolder *src_folder = NULL;
6088
6089         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6090
6091         if (headers) {
6092                 TnyHeader *header = NULL;
6093                 TnyIterator *iter;
6094
6095                 iter = tny_list_create_iterator (headers);
6096                 header = (TnyHeader *) tny_iterator_get_current (iter);
6097                 src_folder = tny_header_get_folder (header);
6098
6099                 /* Transfer the messages */
6100                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
6101                                                             headers,
6102                                                             TNY_FOLDER (dst_folder));
6103
6104                 /* Frees */
6105                 g_object_unref (header);
6106                 g_object_unref (iter);
6107                 g_object_unref (src_folder);
6108         }
6109 }
6110
6111 void
6112 modest_ui_actions_on_move_to (GtkAction *action,
6113                               ModestWindow *win)
6114 {
6115         modest_ui_actions_on_edit_mode_move_to (win);
6116 }
6117
6118 gboolean
6119 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
6120 {
6121         GtkWidget *dialog = NULL;
6122         MoveToInfo *helper = NULL;
6123         TnyList *list_to_move;
6124
6125         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
6126
6127 #ifndef MODEST_TOOLKIT_HILDON2
6128         /* Get the main window if exists */
6129         ModestMainWindow *main_window;
6130         if (MODEST_IS_MAIN_WINDOW (win))
6131                 main_window = MODEST_MAIN_WINDOW (win);
6132         else
6133                 main_window =
6134                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
6135                                                                                FALSE)); /* don't create */
6136 #endif
6137
6138         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
6139
6140         if (!list_to_move)
6141                 return FALSE;
6142
6143         if (tny_list_get_length (list_to_move) < 1) {
6144                 g_object_unref (list_to_move);
6145                 return FALSE;
6146         }
6147
6148         /* Create and run the dialog */
6149         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
6150         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
6151                                      GTK_WINDOW (dialog),
6152                                      (GtkWindow *) win);
6153
6154         /* Create helper */
6155         helper = g_slice_new0 (MoveToInfo);
6156         helper->list = list_to_move;
6157         helper->win = win;
6158
6159         /* Listen to response signal */
6160         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
6161
6162         /* Show the dialog */
6163         gtk_widget_show (dialog);
6164
6165         return FALSE;
6166 }
6167
6168 /*
6169  * Calls #HeadersFunc for each header already selected in the main
6170  * window or the message currently being shown in the msg view window
6171  */
6172 static void
6173 do_headers_action (ModestWindow *win,
6174                    HeadersFunc func,
6175                    gpointer user_data)
6176 {
6177         TnyList *headers_list = NULL;
6178         TnyIterator *iter = NULL;
6179         TnyHeader *header = NULL;
6180         TnyFolder *folder = NULL;
6181
6182         /* Get headers */
6183         headers_list = get_selected_headers (win);
6184         if (!headers_list)
6185                 return;
6186
6187         /* Get the folder */
6188         iter = tny_list_create_iterator (headers_list);
6189         header = TNY_HEADER (tny_iterator_get_current (iter));
6190         if (header) {
6191                 folder = tny_header_get_folder (header);
6192                 g_object_unref (header);
6193         }
6194
6195         /* Call the function for each header */
6196         while (!tny_iterator_is_done (iter)) {
6197                 header = TNY_HEADER (tny_iterator_get_current (iter));
6198                 func (header, win, user_data);
6199                 g_object_unref (header);
6200                 tny_iterator_next (iter);
6201         }
6202
6203         /* Trick: do a poke status in order to speed up the signaling
6204            of observers */
6205         if (folder) {
6206                 tny_folder_poke_status (folder);
6207                 g_object_unref (folder);
6208         }
6209
6210         /* Frees */
6211         g_object_unref (iter);
6212         g_object_unref (headers_list);
6213 }
6214
6215 void
6216 modest_ui_actions_view_attachment (GtkAction *action,
6217                                    ModestWindow *window)
6218 {
6219         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6220                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
6221         } else {
6222                 /* not supported window for this action */
6223                 g_return_if_reached ();
6224         }
6225 }
6226
6227 void
6228 modest_ui_actions_save_attachments (GtkAction *action,
6229                                     ModestWindow *window)
6230 {
6231         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6232
6233                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
6234                         return;
6235
6236                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
6237         } else {
6238                 /* not supported window for this action */
6239                 g_return_if_reached ();
6240         }
6241 }
6242
6243 void
6244 modest_ui_actions_remove_attachments (GtkAction *action,
6245                                       ModestWindow *window)
6246 {
6247         if (MODEST_IS_MAIN_WINDOW (window)) {
6248                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
6249         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6250                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
6251         } else {
6252                 /* not supported window for this action */
6253                 g_return_if_reached ();
6254         }
6255 }
6256
6257 void
6258 modest_ui_actions_on_settings (GtkAction *action,
6259                                ModestWindow *win)
6260 {
6261         GtkWidget *dialog;
6262
6263         dialog = modest_platform_get_global_settings_dialog ();
6264         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
6265         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
6266         gtk_widget_show_all (dialog);
6267
6268         gtk_dialog_run (GTK_DIALOG (dialog));
6269
6270         gtk_widget_destroy (dialog);
6271 }
6272
6273 void
6274 modest_ui_actions_on_help (GtkAction *action,
6275                            GtkWindow *win)
6276 {
6277         /* Help app is not available at all in fremantle */
6278 #ifndef MODEST_TOOLKIT_HILDON2
6279         const gchar *help_id;
6280
6281         g_return_if_fail (win && GTK_IS_WINDOW(win));
6282
6283         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
6284
6285         if (help_id)
6286                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6287 #endif
6288 }
6289
6290 void
6291 modest_ui_actions_on_csm_help (GtkAction *action,
6292                                GtkWindow *win)
6293 {
6294         /* Help app is not available at all in fremantle */
6295 #ifndef MODEST_TOOLKIT_HILDON2
6296
6297         const gchar* help_id = NULL;
6298         GtkWidget *folder_view;
6299         TnyFolderStore *folder_store;
6300
6301         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
6302
6303         /* Get selected folder */
6304         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
6305                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6306         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6307
6308         /* Switch help_id */
6309         if (folder_store && TNY_IS_FOLDER (folder_store))
6310                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
6311
6312         if (folder_store)
6313                 g_object_unref (folder_store);
6314
6315         if (help_id)
6316                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6317         else
6318                 modest_ui_actions_on_help (action, win);
6319 #endif
6320 }
6321
6322 static void
6323 retrieve_contents_cb (ModestMailOperation *mail_op,
6324                       TnyHeader *header,
6325                       gboolean canceled,
6326                       TnyMsg *msg,
6327                       GError *err,
6328                       gpointer user_data)
6329 {
6330         /* We only need this callback to show an error in case of
6331            memory low condition */
6332         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
6333                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
6334         }
6335 }
6336
6337 static void
6338 retrieve_msg_contents_performer (gboolean canceled,
6339                                  GError *err,
6340                                  GtkWindow *parent_window,
6341                                  TnyAccount *account,
6342                                  gpointer user_data)
6343 {
6344         ModestMailOperation *mail_op;
6345         TnyList *headers = TNY_LIST (user_data);
6346
6347         if (err || canceled) {
6348                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
6349                                                                 (GtkWidget *) parent_window, err,
6350                                                                 account, NULL);
6351                 goto out;
6352         }
6353
6354         /* Create mail operation */
6355         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
6356                                                                  modest_ui_actions_disk_operations_error_handler,
6357                                                                  NULL, NULL);
6358         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
6359         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
6360
6361         /* Frees */
6362         g_object_unref (mail_op);
6363  out:
6364         g_object_unref (headers);
6365         g_object_unref (account);
6366 }
6367
6368 void
6369 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
6370                                             ModestWindow *window)
6371 {
6372         TnyList *headers = NULL;
6373         TnyAccount *account = NULL;
6374         TnyIterator *iter = NULL;
6375         TnyHeader *header = NULL;
6376         TnyFolder *folder = NULL;
6377
6378         /* Get headers */
6379         headers = get_selected_headers (window);
6380         if (!headers)
6381                 return;
6382
6383         /* Pick the account */
6384         iter = tny_list_create_iterator (headers);
6385         header = TNY_HEADER (tny_iterator_get_current (iter));
6386         folder = tny_header_get_folder (header);
6387         account = tny_folder_get_account (folder);
6388         g_object_unref (folder);
6389         g_object_unref (header);
6390         g_object_unref (iter);
6391
6392         /* Connect and perform the message retrieval */
6393         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
6394                                              g_object_ref (account),
6395                                              retrieve_msg_contents_performer,
6396                                              g_object_ref (headers));
6397
6398         /* Frees */
6399         g_object_unref (account);
6400         g_object_unref (headers);
6401 }
6402
6403 void
6404 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
6405 {
6406         g_return_if_fail (MODEST_IS_WINDOW (window));
6407
6408         /* Update dimmed */
6409         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
6410 }
6411
6412 void
6413 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
6414 {
6415         g_return_if_fail (MODEST_IS_WINDOW (window));
6416
6417         /* Update dimmed */
6418         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
6419 }
6420
6421 void
6422 modest_ui_actions_on_email_menu_activated (GtkAction *action,
6423                                           ModestWindow *window)
6424 {
6425         g_return_if_fail (MODEST_IS_WINDOW (window));
6426
6427         /* Update dimmed */
6428         modest_ui_actions_check_menu_dimming_rules (window);
6429 }
6430
6431 void
6432 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
6433                                           ModestWindow *window)
6434 {
6435         g_return_if_fail (MODEST_IS_WINDOW (window));
6436
6437         /* Update dimmed */
6438         modest_ui_actions_check_menu_dimming_rules (window);
6439 }
6440
6441 void
6442 modest_ui_actions_on_view_menu_activated (GtkAction *action,
6443                                           ModestWindow *window)
6444 {
6445         g_return_if_fail (MODEST_IS_WINDOW (window));
6446
6447         /* Update dimmed */
6448         modest_ui_actions_check_menu_dimming_rules (window);
6449 }
6450
6451 void
6452 modest_ui_actions_on_format_menu_activated (GtkAction *action,
6453                                             ModestWindow *window)
6454 {
6455         g_return_if_fail (MODEST_IS_WINDOW (window));
6456
6457         /* Update dimmed */
6458         modest_ui_actions_check_menu_dimming_rules (window);
6459 }
6460
6461 void
6462 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
6463                                           ModestWindow *window)
6464 {
6465         g_return_if_fail (MODEST_IS_WINDOW (window));
6466
6467         /* Update dimmed */
6468         modest_ui_actions_check_menu_dimming_rules (window);
6469 }
6470
6471 void
6472 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
6473                                           ModestWindow *window)
6474 {
6475         g_return_if_fail (MODEST_IS_WINDOW (window));
6476
6477         /* Update dimmed */
6478         modest_ui_actions_check_menu_dimming_rules (window);
6479 }
6480
6481 void
6482 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
6483                                                  ModestWindow *window)
6484 {
6485         g_return_if_fail (MODEST_IS_WINDOW (window));
6486
6487         /* Update dimmed */
6488         modest_ui_actions_check_menu_dimming_rules (window);
6489 }
6490
6491 void
6492 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
6493                                                      ModestWindow *window)
6494 {
6495         g_return_if_fail (MODEST_IS_WINDOW (window));
6496
6497         /* Update dimmed */
6498         modest_ui_actions_check_menu_dimming_rules (window);
6499 }
6500
6501 void
6502 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
6503                                                      ModestWindow *window)
6504 {
6505         g_return_if_fail (MODEST_IS_WINDOW (window));
6506
6507         /* Update dimmed */
6508         modest_ui_actions_check_menu_dimming_rules (window);
6509 }
6510
6511 void
6512 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6513 {
6514         g_return_if_fail (MODEST_IS_WINDOW (window));
6515
6516         /* we check for low-mem; in that case, show a warning, and don't allow
6517          * searching
6518          */
6519         if (modest_platform_check_memory_low (window, TRUE))
6520                 return;
6521
6522         modest_platform_show_search_messages (GTK_WINDOW (window));
6523 }
6524
6525 void
6526 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6527 {
6528         g_return_if_fail (MODEST_IS_WINDOW (win));
6529
6530
6531         /* we check for low-mem; in that case, show a warning, and don't allow
6532          * for the addressbook
6533          */
6534         if (modest_platform_check_memory_low (win, TRUE))
6535                 return;
6536
6537
6538         modest_platform_show_addressbook (GTK_WINDOW (win));
6539 }
6540
6541
6542 void
6543 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
6544                                           ModestWindow *window)
6545 {
6546         gboolean active;
6547         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6548
6549         if (GTK_IS_TOGGLE_ACTION (action))
6550                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
6551         else
6552                 active = TRUE;
6553
6554         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window),
6555                                                     active);
6556 }
6557
6558 static void
6559 on_send_receive_finished (ModestMailOperation  *mail_op,
6560                            gpointer user_data)
6561 {
6562         GtkWidget *header_view, *folder_view;
6563         TnyFolderStore *folder_store;
6564         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6565
6566         /* Set send/receive operation finished */
6567         modest_main_window_notify_send_receive_completed (main_win);
6568
6569         /* Don't refresh the current folder if there were any errors */
6570         if (modest_mail_operation_get_status (mail_op) !=
6571             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6572                 return;
6573
6574         /* Refresh the current folder if we're viewing a window. We do
6575            this because the user won't be able to see the new mails in
6576            the selected folder after a Send&Receive because it only
6577            performs a poke_status, i.e, only the number of read/unread
6578            messages is updated, but the new headers are not
6579            downloaded */
6580         folder_view = modest_main_window_get_child_widget (main_win,
6581                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6582         if (!folder_view)
6583                 return;
6584
6585         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6586
6587         /* Do not need to refresh INBOX again because the
6588            update_account does it always automatically */
6589         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6590             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6591                 ModestMailOperation *refresh_op;
6592
6593                 header_view = modest_main_window_get_child_widget (main_win,
6594                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6595
6596                 /* We do not need to set the contents style
6597                    because it hasn't changed. We also do not
6598                    need to save the widget status. Just force
6599                    a refresh */
6600                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6601                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6602                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6603                                                       folder_refreshed_cb, main_win);
6604                 g_object_unref (refresh_op);
6605         }
6606
6607         if (folder_store)
6608                 g_object_unref (folder_store);
6609 }
6610
6611
6612 void
6613 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6614                                                 TnyHeader *header,
6615                                                 TnyMsg *msg,
6616                                                 GError *err,
6617                                                 gpointer user_data)
6618 {
6619         const gchar* server_name = NULL;
6620         TnyTransportAccount *transport;
6621         gchar *message = NULL;
6622         ModestProtocol *protocol;
6623
6624         /* Don't show anything if the user cancelled something or the
6625          * send receive request is not interactive. Authentication
6626          * errors are managed by the account store so no need to show
6627          * a dialog here again */
6628         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6629             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6630             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6631                 return;
6632
6633
6634         /* Get the server name. Note that we could be using a
6635            connection specific transport account */
6636         transport = (TnyTransportAccount *)
6637                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
6638         if (transport) {
6639                 ModestTnyAccountStore *acc_store;
6640                 const gchar *acc_name;
6641                 TnyTransportAccount *conn_specific;
6642
6643                 acc_store = modest_runtime_get_account_store();
6644                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
6645                 conn_specific = (TnyTransportAccount *)
6646                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
6647                 if (conn_specific) {
6648                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
6649                         g_object_unref (conn_specific);
6650                 } else {
6651                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
6652                 }
6653                 g_object_unref (transport);
6654         }
6655
6656         /* Get protocol */
6657         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
6658                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
6659                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
6660         if (!protocol) {
6661                 g_warning ("%s: Account with no proto", __FUNCTION__);
6662                 return;
6663         }
6664
6665         /* Show the appropriate message text for the GError: */
6666         switch (err->code) {
6667         case TNY_SERVICE_ERROR_CONNECT:
6668                 message = modest_protocol_get_translation (protocol,
6669                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
6670                                                            server_name);
6671                 break;
6672         case TNY_SERVICE_ERROR_SEND:
6673                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6674                 break;
6675         case TNY_SERVICE_ERROR_UNAVAILABLE:
6676                 message = modest_protocol_get_translation (protocol,
6677                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
6678                                                            server_name);
6679                 break;
6680         default:
6681                 g_warning ("%s: unexpected ERROR %d",
6682                            __FUNCTION__, err->code);
6683                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6684                 break;
6685         }
6686
6687         modest_platform_run_information_dialog (NULL, message, FALSE);
6688         g_free (message);
6689 }
6690
6691 void
6692 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6693                                                 gchar *msg_id,
6694                                                 guint status,
6695                                                 gpointer user_data)
6696 {
6697         ModestWindow *top_window = NULL;
6698         ModestWindowMgr *mgr = NULL;
6699         GtkWidget *header_view = NULL;
6700         TnyFolder *selected_folder = NULL;
6701         TnyFolderType folder_type;
6702
6703         mgr = modest_runtime_get_window_mgr ();
6704         top_window = modest_window_mgr_get_current_top (mgr);
6705
6706         if (!top_window)
6707                 return;
6708
6709 #ifndef MODEST_TOOLKIT_HILDON2
6710         if (MODEST_IS_MAIN_WINDOW (top_window)) {
6711                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (top_window),
6712                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6713         }
6714 #else
6715         if (MODEST_IS_HEADER_WINDOW (top_window)) {
6716                 header_view = (GtkWidget *)
6717                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
6718         }
6719 #endif
6720
6721         /* Get selected folder */
6722         if (header_view)
6723                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
6724         if (!selected_folder)
6725                 return;
6726
6727         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6728 #if GTK_CHECK_VERSION(2, 8, 0)
6729         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
6730         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
6731                 GtkTreeViewColumn *tree_column;
6732
6733                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
6734                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6735                 if (tree_column)
6736                         gtk_tree_view_column_queue_resize (tree_column);
6737                 }
6738 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
6739         gtk_widget_queue_draw (header_view);
6740 #endif
6741
6742 #ifndef MODEST_TOOLKIT_HILDON2
6743         /* Rerun dimming rules, because the message could become deletable for example */
6744         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6745                                                  MODEST_DIMMING_RULES_TOOLBAR);
6746         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6747                                                  MODEST_DIMMING_RULES_MENU);
6748 #endif
6749
6750         /* Free */
6751         g_object_unref (selected_folder);
6752 }
6753
6754 void
6755 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6756                                                TnyAccount *account)
6757 {
6758         ModestProtocolType protocol_type;
6759         ModestProtocol *protocol;
6760         gchar *error_note = NULL;
6761
6762         protocol_type = modest_tny_account_get_protocol_type (account);
6763         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6764                                                                   protocol_type);
6765
6766         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6767         if (error_note == NULL) {
6768                 g_warning ("%s: This should not be reached", __FUNCTION__);
6769         } else {
6770                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6771                 g_free (error_note);
6772         }
6773 }
6774
6775 gchar *
6776 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6777 {
6778         gchar *msg = NULL;
6779         gchar *subject;
6780         TnyFolderStore *folder = NULL;
6781         TnyAccount *account = NULL;
6782         ModestProtocolType proto;
6783         ModestProtocol *protocol;
6784         TnyHeader *header = NULL;
6785
6786         if (MODEST_IS_MAIN_WINDOW (win)) {
6787                 GtkWidget *header_view;
6788                 TnyList* headers = NULL;
6789                 TnyIterator *iter;
6790                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6791                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6792                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6793                 if (!headers || tny_list_get_length (headers) == 0) {
6794                         if (headers)
6795                                 g_object_unref (headers);
6796                         return NULL;
6797                 }
6798                 iter = tny_list_create_iterator (headers);
6799                 header = TNY_HEADER (tny_iterator_get_current (iter));
6800                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6801                 g_object_unref (iter);
6802                 g_object_unref (headers);
6803 #ifdef MODEST_TOOLKIT_HILDON2
6804         } else if (MODEST_IS_HEADER_WINDOW (win)) {
6805                 GtkWidget *header_view;
6806                 TnyList* headers = NULL;
6807                 TnyIterator *iter;
6808                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
6809                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6810                 if (!headers || tny_list_get_length (headers) == 0) {
6811                         if (headers)
6812                                 g_object_unref (headers);
6813                         return NULL;
6814                 }
6815                 iter = tny_list_create_iterator (headers);
6816                 header = TNY_HEADER (tny_iterator_get_current (iter));
6817                 if (header) {
6818                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6819                 } else {
6820                         g_warning ("List should contain headers");
6821                 }
6822                 g_object_unref (iter);
6823                 g_object_unref (headers);
6824 #endif
6825         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6826                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6827                 if (header)
6828                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6829         }
6830
6831         if (!header || !folder)
6832                 goto frees;
6833
6834         /* Get the account type */
6835         account = tny_folder_get_account (TNY_FOLDER (folder));
6836         proto = modest_tny_account_get_protocol_type (account);
6837         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6838                                                                   proto);
6839
6840         subject = tny_header_dup_subject (header);
6841         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6842         if (subject)
6843                 g_free (subject);
6844         if (msg == NULL) {
6845                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6846         }
6847
6848  frees:
6849         /* Frees */
6850         if (account)
6851                 g_object_unref (account);
6852         if (folder)
6853                 g_object_unref (folder);
6854         if (header)
6855                 g_object_unref (header);
6856
6857         return msg;
6858 }
6859
6860 gboolean
6861 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6862                                      const gchar *account_name,
6863                                      const gchar *account_title)
6864 {
6865         ModestAccountMgr *account_mgr;
6866         gchar *txt = NULL;
6867         gint response;
6868         ModestProtocol *protocol;
6869         gboolean removed = FALSE;
6870
6871         g_return_val_if_fail (account_name, FALSE);
6872         g_return_val_if_fail (account_title, FALSE);
6873
6874         account_mgr = modest_runtime_get_account_mgr();
6875
6876         /* The warning text depends on the account type: */
6877         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6878                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6879                                                                                                          account_name));
6880         txt = modest_protocol_get_translation (protocol,
6881                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6882                                                account_title);
6883         if (txt == NULL)
6884                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6885
6886         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6887         g_free (txt);
6888         txt = NULL;
6889
6890         if (response == GTK_RESPONSE_OK) {
6891                 /* Remove account. If it succeeds then it also removes
6892                    the account from the ModestAccountView: */
6893                 gboolean is_default = FALSE;
6894                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6895                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6896                         is_default = TRUE;
6897                 g_free (default_account_name);
6898
6899                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6900                 if (removed) {
6901                         /* Close all email notifications, we cannot
6902                            distinguish if the notification belongs to
6903                            this account or not, so for safety reasons
6904                            we remove them all */
6905                         modest_platform_remove_new_mail_notifications (FALSE);
6906                 } else {
6907                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6908                 }
6909         }
6910         return removed;
6911 }
6912
6913 static void
6914 on_fetch_images_performer (gboolean canceled,
6915                            GError *err,
6916                            GtkWindow *parent_window,
6917                            TnyAccount *account,
6918                            gpointer user_data)
6919 {
6920         if (err || canceled) {
6921                 /* Show an unable to retrieve images ??? */
6922                 return;
6923         }
6924
6925         /* Note that the user could have closed the window while connecting */
6926         if (GTK_WIDGET_VISIBLE (parent_window))
6927                 modest_msg_view_window_fetch_images ((ModestMsgViewWindow *) parent_window);
6928         g_object_unref ((GObject *) user_data);
6929 }
6930
6931 void
6932 modest_ui_actions_on_fetch_images (GtkAction *action,
6933                                    ModestWindow *window)
6934 {
6935         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
6936
6937         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE, 
6938                                              NULL,
6939                                              on_fetch_images_performer, 
6940                                              g_object_ref (window));
6941 }
6942
6943 void
6944 modest_ui_actions_on_reload_message (const gchar *msg_id)
6945 {
6946         ModestWindow *window = NULL;
6947
6948         g_return_if_fail (msg_id && msg_id[0] != '\0');
6949         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
6950                                                             msg_id,
6951                                                             &window))
6952                 return;
6953
6954
6955         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
6956                 return;
6957
6958         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
6959 }
6960
6961 /** Check whether any connections are active, and cancel them if 
6962  * the user wishes.
6963  * Returns TRUE is there was no problem, 
6964  * or if an operation was cancelled so we can continue.
6965  * Returns FALSE if the user chose to cancel his request instead.
6966  */
6967
6968 gboolean
6969 modest_ui_actions_check_for_active_account (ModestWindow *self,
6970                                             const gchar* account_name)
6971 {
6972         ModestTnySendQueue *send_queue;
6973         ModestTnyAccountStore *acc_store;
6974         ModestMailOperationQueue* queue;
6975         TnyConnectionStatus store_conn_status;
6976         TnyAccount *store_account = NULL, *transport_account = NULL;
6977         gboolean retval = TRUE, sending = FALSE;
6978
6979         acc_store = modest_runtime_get_account_store ();
6980         queue = modest_runtime_get_mail_operation_queue ();
6981
6982         store_account = 
6983                 modest_tny_account_store_get_server_account (acc_store,
6984                                                              account_name,
6985                                                              TNY_ACCOUNT_TYPE_STORE);
6986
6987         /* This could happen if the account was deleted before the
6988            call to this function */
6989         if (!store_account)
6990                 return FALSE;
6991
6992         transport_account = 
6993                 modest_tny_account_store_get_server_account (acc_store,
6994                                                              account_name,
6995                                                              TNY_ACCOUNT_TYPE_TRANSPORT);
6996
6997         /* This could happen if the account was deleted before the
6998            call to this function */
6999         if (!transport_account) {
7000                 g_object_unref (store_account);
7001                 return FALSE;
7002         }
7003
7004         /* If the transport account was not used yet, then the send
7005            queue could not exist (it's created on demand) */
7006         send_queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (transport_account), FALSE);
7007         if (TNY_IS_SEND_QUEUE (send_queue))
7008                 sending = modest_tny_send_queue_sending_in_progress (send_queue);
7009
7010         store_conn_status = tny_account_get_connection_status (store_account);
7011         if (store_conn_status == TNY_CONNECTION_STATUS_CONNECTED || sending) {
7012                 gint response;
7013
7014                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (self), 
7015                                                                 _("emev_nc_disconnect_account"));
7016                 if (response == GTK_RESPONSE_OK) {
7017                         retval = TRUE;
7018                 } else {
7019                         retval = FALSE;
7020                 }
7021         }
7022
7023         if (retval) {
7024
7025                 /* FIXME: We should only cancel those of this account */
7026                 modest_mail_operation_queue_cancel_all (queue);
7027
7028                 /* Also disconnect the account */
7029                 if ((tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED) &&
7030                     (tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED_BROKEN)) {
7031                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account),
7032                                                       FALSE, NULL, NULL);
7033                 }
7034                 if (sending) {
7035                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (transport_account),
7036                                                       FALSE, NULL, NULL);
7037                 }
7038         }
7039                 
7040         /* Frees */
7041         g_object_unref (store_account);
7042         g_object_unref (transport_account);
7043         
7044         return retval;
7045 }