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