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