This commit implements a new handling of image attachments. We follow
[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-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
44
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include <tny-mime-part.h>
48 #include <tny-camel-folder.h>
49 #include <tny-camel-imap-folder.h>
50 #include <tny-camel-pop-folder.h>
51
52 #ifdef MODEST_PLATFORM_MAEMO
53 #include "maemo/modest-osso-state-saving.h"
54 #include "maemo/modest-maemo-utils.h"
55 #include "maemo/modest-hildon-includes.h"
56 #endif /* MODEST_PLATFORM_MAEMO */
57
58 #include "widgets/modest-ui-constants.h"
59 #include <widgets/modest-main-window.h>
60 #include <widgets/modest-msg-view-window.h>
61 #include <widgets/modest-account-view-window.h>
62 #include <widgets/modest-details-dialog.h>
63 #include <widgets/modest-attachments-view.h>
64 #include "widgets/modest-folder-view.h"
65 #include "widgets/modest-global-settings-dialog.h"
66 #include "modest-connection-specific-smtp-window.h"
67 #include "modest-account-mgr-helpers.h"
68 #include "modest-mail-operation.h"
69 #include "modest-text-utils.h"
70
71 #ifdef MODEST_HAVE_EASYSETUP
72 #include "easysetup/modest-easysetup-wizard.h"
73 #endif /* MODEST_HAVE_EASYSETUP */
74
75 #include <modest-widget-memory.h>
76 #include <tny-error.h>
77 #include <tny-simple-list.h>
78 #include <tny-msg-view.h>
79 #include <tny-device.h>
80 #include <tny-merge-folder.h>
81
82 #include <gtkhtml/gtkhtml.h>
83
84 typedef struct _GetMsgAsyncHelper {     
85         ModestWindow *window;
86         ModestMailOperation *mail_op;
87         TnyIterator *iter;
88         guint num_ops;
89         GFunc func;     
90         gpointer user_data;
91 } GetMsgAsyncHelper;
92
93 typedef enum _ReplyForwardAction {
94         ACTION_REPLY,
95         ACTION_REPLY_TO_ALL,
96         ACTION_FORWARD
97 } ReplyForwardAction;
98
99 typedef struct _ReplyForwardHelper {
100         guint reply_forward_type;
101         ReplyForwardAction action;
102         gchar *account_name;
103         GtkWidget *parent_window;
104 } ReplyForwardHelper;
105
106 typedef struct _MoveToHelper {
107         GtkTreeRowReference *reference;
108         GtkWidget *banner;
109 } MoveToHelper;
110
111 typedef struct _PasteAsAttachmentHelper {
112         ModestMsgEditWindow *window;
113         GtkWidget *banner;
114 } PasteAsAttachmentHelper;
115
116
117 /*
118  * The do_headers_action uses this kind of functions to perform some
119  * action to each member of a list of headers
120  */
121 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
122
123 static void     do_headers_action     (ModestWindow *win, 
124                                        HeadersFunc func,
125                                        gpointer user_data);
126
127 static void     open_msg_cb            (ModestMailOperation *mail_op, 
128                                         TnyHeader *header, 
129                                         TnyMsg *msg,
130                                         gpointer user_data);
131
132 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
133                                         TnyHeader *header, 
134                                         TnyMsg *msg,
135                                         gpointer user_data);
136
137 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
138
139 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
140                                         TnyFolder *folder, 
141                                         gpointer user_data);
142
143 static void     _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
144                                                    ModestMailOperationState *state,
145                                                    gpointer user_data);
146
147 static gint header_list_count_uncached_msgs (TnyList *header_list);
148 static gboolean connect_to_get_msg (
149                                                 GtkWindow *win,
150                                                 gint num_of_uncached_msgs);
151
152 static gboolean remote_folder_is_pop (const TnyFolderStore *folder);
153
154 static gboolean msgs_already_deleted_from_server ( TnyList *headers,
155                                                    const TnyFolderStore *src_folder);
156
157
158 /*
159  * This function checks whether a TnyFolderStore is a pop account
160  */
161 static gboolean
162 remote_folder_is_pop (const TnyFolderStore *folder)
163 {
164         const gchar *proto = NULL;
165         TnyAccount *account = NULL;
166
167         g_return_val_if_fail (TNY_IS_FOLDER_STORE(folder), FALSE);
168
169         if (TNY_IS_ACCOUNT (folder)) {
170                 account = TNY_ACCOUNT(folder);
171                 g_object_ref(account);
172         } else if (TNY_IS_FOLDER (folder)) {
173                 account = tny_folder_get_account(TNY_FOLDER(folder));
174         }
175
176         proto = tny_account_get_proto(account);
177         g_object_unref (account);
178
179         return proto &&
180           (modest_protocol_info_get_transport_store_protocol (proto) == MODEST_PROTOCOL_STORE_POP);
181 }
182
183 /*
184  * This functions checks whether if a list of messages are already
185  * deleted from the server: that is, if the server is a POP account
186  * and all messages are already cached.
187  */
188 static gboolean
189 msgs_already_deleted_from_server (TnyList *headers, const TnyFolderStore *src_folder)
190 {
191         g_return_val_if_fail (TNY_IS_FOLDER_STORE(src_folder), FALSE);
192         g_return_val_if_fail (TNY_IS_LIST(headers), FALSE);
193
194         gboolean src_is_pop = remote_folder_is_pop (src_folder);
195         gint uncached_msgs = header_list_count_uncached_msgs (headers);
196
197         return (src_is_pop && !uncached_msgs);
198 }
199
200
201 /* FIXME: this should be merged with the similar code in modest-account-view-window */
202 /* Show the account creation wizard dialog.
203  * returns: TRUE if an account was created. FALSE if the user cancelled.
204  */
205 gboolean
206 modest_run_account_setup_wizard (ModestWindow *win)
207 {
208         gboolean result = FALSE;
209         GtkDialog *wizard, *dialog;
210
211         /* Show the easy-setup wizard: */       
212         dialog = modest_window_mgr_get_modal_dialog (modest_runtime_get_window_mgr());
213         if (dialog && MODEST_IS_EASYSETUP_WIZARD_DIALOG(dialog)) {
214                 /* old wizard is active already; 
215                  */
216                 gtk_window_present (GTK_WINDOW(dialog));
217                 return FALSE;
218         }
219         
220
221         /* there is no such wizard yet */
222                 
223         wizard = GTK_DIALOG(modest_easysetup_wizard_dialog_new ());
224         if (!wizard) {
225                 g_printerr ("modest: failed to create easysetup wizard\n");
226                 return FALSE;
227         }
228         
229         modest_window_mgr_set_modal_dialog
230                 (modest_runtime_get_window_mgr(), GTK_DIALOG(wizard));
231
232
233         /* there is no such wizard yet */
234         wizard = GTK_DIALOG(modest_easysetup_wizard_dialog_new ());
235         modest_window_mgr_set_modal_dialog (modest_runtime_get_window_mgr(), 
236                                             GTK_DIALOG(wizard));
237
238         /* make it non-modal; if though we register it as a modal dialog above
239          * apparently, making it modal *at all* gives hangs -- FIXME: check this*/
240         gtk_window_set_modal (GTK_WINDOW(dialog), FALSE);
241
242         /* always present a main window in the background 
243          * we do it here, so we cannot end up with to wizards (as this
244          * function might be called in modest_window_mgr_get_main_window as well */
245         if (!win) 
246                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr());
247
248         /* make sure the mainwindow is visible */
249         gtk_widget_show_all (GTK_WIDGET(win));
250         gtk_window_present (GTK_WINDOW(win));
251
252         
253         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
254
255         /* Don't make this a modal window, because secondary windows will then 
256          * be unusable, freezing the UI: */
257         /* gtk_window_set_modal (GTK_WINDOW (wizard), TRUE); */
258         
259         gint dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
260         if (dialog_response == GTK_RESPONSE_CANCEL)
261                 result = FALSE;
262         else {
263                 /* Check whether an account was created: */
264                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
265         }
266         
267         gtk_widget_destroy (GTK_WIDGET (wizard));
268
269         /* clear it from the window mgr */
270         modest_window_mgr_set_modal_dialog
271                 (modest_runtime_get_window_mgr(), NULL);
272         
273         return result;
274 }
275
276
277 void   
278 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
279 {
280         GtkWidget *about;
281         const gchar *authors[] = {
282                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
283                 NULL
284         };
285         about = gtk_about_dialog_new ();
286         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
287         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
288         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
289                                         _("Copyright (c) 2006, Nokia Corporation\n"
290                                           "All rights reserved."));
291         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
292                                        _("a modest e-mail client\n\n"
293                                          "design and implementation: Dirk-Jan C. Binnema\n"
294                                          "contributions from the fine people at KC and Ig\n"
295                                          "uses the tinymail email framework written by Philip van Hoof"));
296         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
297         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
298         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
299         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
300         
301         gtk_dialog_run (GTK_DIALOG (about));
302         gtk_widget_destroy(about);
303 }
304
305 /*
306  * Gets the list of currently selected messages. If the win is the
307  * main window, then it returns a newly allocated list of the headers
308  * selected in the header view. If win is the msg view window, then
309  * the value returned is a list with just a single header.
310  *
311  * The caller of this funcion must free the list.
312  */
313 static TnyList *
314 get_selected_headers (ModestWindow *win)
315 {
316         if (MODEST_IS_MAIN_WINDOW(win)) {
317                 GtkWidget *header_view;         
318                 
319                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
320                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
321                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
322                 
323         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
324                 /* for MsgViewWindows, we simply return a list with one element */
325                 TnyHeader *header;
326                 TnyList *list = NULL;
327                 
328                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
329                 if (header != NULL) {
330                         list = tny_simple_list_new ();
331                         tny_list_prepend (list, G_OBJECT(header));
332                         g_object_unref (G_OBJECT(header));
333                 }
334
335                 return list;
336
337         } else
338                 return NULL;
339 }
340
341 static GtkTreeRowReference *
342 get_next_after_selected_headers (ModestHeaderView *header_view)
343 {
344         GtkTreeSelection *sel;
345         GList *selected_rows, *node;
346         GtkTreePath *path;
347         GtkTreeRowReference *result;
348         GtkTreeModel *model;
349
350         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
351         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
352         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
353
354         if (selected_rows == NULL)
355                 return NULL;
356
357         node = g_list_last (selected_rows);
358         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
359         gtk_tree_path_next (path);
360
361         result = gtk_tree_row_reference_new (model, path);
362
363         gtk_tree_path_free (path);
364         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
365         g_list_free (selected_rows);
366
367         return result;
368 }
369
370 static void
371 headers_action_mark_as_read (TnyHeader *header,
372                              ModestWindow *win,
373                              gpointer user_data)
374 {
375         TnyHeaderFlags flags;
376
377         g_return_if_fail (TNY_IS_HEADER(header));
378
379         flags = tny_header_get_flags (header);
380         if (flags & TNY_HEADER_FLAG_SEEN) return;
381         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
382 }
383
384 static void
385 headers_action_mark_as_unread (TnyHeader *header,
386                                ModestWindow *win,
387                                gpointer user_data)
388 {
389         TnyHeaderFlags flags;
390
391         g_return_if_fail (TNY_IS_HEADER(header));
392
393         flags = tny_header_get_flags (header);
394         if (flags & TNY_HEADER_FLAG_SEEN)  {
395                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
396         }
397 }
398
399 /** A convenience method, because deleting a message is 
400  * otherwise complicated, and it's best to change it in one place 
401  * when we change it.
402  */
403 void modest_do_message_delete (TnyHeader *header, ModestWindow *win)
404 {
405         ModestMailOperation *mail_op = NULL;
406         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, 
407                 win ? G_OBJECT(win) : NULL);
408         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
409                                          mail_op);
410         
411         /* Always delete. TODO: Move to trash still not supported */
412         modest_mail_operation_remove_msg (mail_op, header, FALSE);
413         g_object_unref (G_OBJECT (mail_op));
414 }
415
416 /** A convenience method, because deleting a message is 
417  * otherwise complicated, and it's best to change it in one place 
418  * when we change it.
419  */
420 void modest_do_messages_delete (TnyList *headers, ModestWindow *win)
421 {
422         ModestMailOperation *mail_op = NULL;
423         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, 
424                 win ? G_OBJECT(win) : NULL);
425         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
426                                          mail_op);
427         
428         /* Always delete. TODO: Move to trash still not supported */
429         modest_mail_operation_remove_msgs (mail_op, headers, FALSE);
430         g_object_unref (G_OBJECT (mail_op));
431 }
432
433 /** After deleing a message that is currently visible in a window, 
434  * show the next message from the list, or close the window if there are no more messages.
435  **/
436 void 
437 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
438 {
439         /* Close msg view window or select next */
440         if (modest_msg_view_window_last_message_selected (win) &&
441                 modest_msg_view_window_first_message_selected (win)) {
442                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
443         } else if (!modest_msg_view_window_select_next_message (win)) {
444                 gboolean ret_value;
445                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);       
446         }
447 }
448
449 void
450 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
451 {
452         TnyList *header_list = NULL;
453         TnyIterator *iter = NULL;
454         TnyHeader *header = NULL;
455         gchar *message = NULL;
456         gchar *desc = NULL;
457         gint response;
458         ModestWindowMgr *mgr;
459         GtkWidget *header_view = NULL;
460
461         g_return_if_fail (MODEST_IS_WINDOW(win));
462         
463         /* Check first if the header view has the focus */
464         if (MODEST_IS_MAIN_WINDOW (win)) {
465                 header_view = 
466                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
467                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
468                 if (!gtk_widget_is_focus (header_view))
469                         return;
470         }
471         
472         /* Get the headers, either from the header view (if win is the main window),
473          * or from the message view window: */
474         header_list = get_selected_headers (win);
475         if (!header_list) return;
476                         
477         /* Check if any of the headers are already opened, or in the process of being opened */
478         if (MODEST_IS_MAIN_WINDOW (win)) {
479                 gint opened_headers = 0;
480
481                 iter = tny_list_create_iterator (header_list);
482                 mgr = modest_runtime_get_window_mgr ();
483                 while (!tny_iterator_is_done (iter)) {
484                         header = TNY_HEADER (tny_iterator_get_current (iter));
485                         if (header) {
486                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
487                                         opened_headers++;
488                                 g_object_unref (header);
489                         }
490                         tny_iterator_next (iter);
491                 }
492                 g_object_unref (iter);
493
494                 if (opened_headers > 0) {
495                         gchar *msg;
496
497                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), 
498                                                opened_headers);
499
500                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
501                         
502                         g_free (msg);
503                         g_object_unref (header_list);
504                         return;
505                 }
506         }
507
508         /* Select message */
509         if (tny_list_get_length(header_list) == 1) {
510                 iter = tny_list_create_iterator (header_list);
511                 header = TNY_HEADER (tny_iterator_get_current (iter));
512                 if (header) {
513                         desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
514                         g_object_unref (header);
515                 }
516
517                 g_object_unref (iter);
518         }
519         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
520                                            tny_list_get_length(header_list)), desc);
521
522         /* Confirmation dialog */
523         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
524                                                             message);
525         
526
527         if (response == GTK_RESPONSE_OK) {      
528                 ModestWindow *main_window = NULL;
529                 ModestWindowMgr *mgr = NULL;
530                 GtkTreeModel *model = NULL;
531                 GtkTreeSelection *sel = NULL;
532                 GList *sel_list = NULL, *tmp = NULL;
533                 GtkTreeRowReference *next_row_reference = NULL;
534                 GtkTreeRowReference *prev_row_reference = NULL;
535                 GtkTreePath *next_path = NULL;
536                 GtkTreePath *prev_path = NULL;
537                 GError *err = NULL;
538
539                 /* Find last selected row */                    
540                 if (MODEST_IS_MAIN_WINDOW (win)) {
541                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
542                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
543                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
544                         for (tmp=sel_list; tmp; tmp=tmp->next) {
545                                 if (tmp->next == NULL) {
546                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
547                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
548
549                                         gtk_tree_path_prev (prev_path);
550                                         gtk_tree_path_next (next_path);
551
552                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
553                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
554                                 }
555                         }
556                 }
557                 
558                 /* Disable window dimming management */
559                 modest_window_disable_dimming (MODEST_WINDOW(win));
560
561                 /* Remove each header. If it's a view window header_view == NULL */
562                 modest_do_messages_delete (header_list, win);
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);
576                 }
577                 else {                  
578                         /* Move cursor to next row */
579                         main_window = win; 
580
581                         /* Select next or previous row */
582                         if (gtk_tree_row_reference_valid (next_row_reference)) {
583 /*                              next_path = gtk_tree_row_reference_get_path (row_reference); */
584                                 gtk_tree_selection_select_path (sel, next_path);
585                         }
586                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {                           
587                                 gtk_tree_selection_select_path (sel, prev_path);
588                         }
589
590                         /* Free */
591                         if (next_row_reference != NULL) 
592                                 gtk_tree_row_reference_free (next_row_reference);
593                         if (next_path != NULL) 
594                                 gtk_tree_path_free (next_path);                         
595                         if (prev_row_reference != NULL) 
596                                 gtk_tree_row_reference_free (prev_row_reference);
597                         if (prev_path != NULL) 
598                                 gtk_tree_path_free (prev_path);                         
599                 }
600
601                 if (err != NULL) {
602                         printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, err->code, err->message);
603                         g_error_free(err);
604                 }
605                 
606                 /* Update toolbar dimming state */
607                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
608
609                 /* Free */
610                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
611                 g_list_free (sel_list);
612         }
613
614         /* Free*/
615         g_free(message);
616         g_free(desc);
617         g_object_unref (header_list);
618 }
619
620
621
622
623 /* delete either message or folder, based on where we are */
624 void
625 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
626 {
627         g_return_if_fail (MODEST_IS_WINDOW(win));
628         
629         /* Check first if the header view has the focus */
630         if (MODEST_IS_MAIN_WINDOW (win)) {
631                 GtkWidget *w;
632                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
633                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
634                 if (gtk_widget_is_focus (w)) {
635                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
636                         return;
637                 }
638         }
639         modest_ui_actions_on_delete_message (action, win);
640 }
641
642
643
644 void
645 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
646 {       
647         ModestWindowMgr *mgr = NULL;
648         
649 #ifdef MODEST_PLATFORM_MAEMO
650         modest_osso_save_state();
651 #endif /* MODEST_PLATFORM_MAEMO */
652
653         g_debug ("closing down, clearing %d item(s) from operation queue",
654                  modest_mail_operation_queue_num_elements
655                  (modest_runtime_get_mail_operation_queue()));
656
657         /* cancel all outstanding operations */
658         modest_mail_operation_queue_cancel_all 
659                 (modest_runtime_get_mail_operation_queue());
660         
661         g_debug ("queue has been cleared");
662
663
664         /* Check if there are opened editing windows */ 
665         mgr = modest_runtime_get_window_mgr ();
666         modest_window_mgr_close_all_windows (mgr);
667
668         /* note: when modest-tny-account-store is finalized,
669            it will automatically set all network connections
670            to offline */
671
672 /*      gtk_main_quit (); */
673 }
674
675 void
676 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
677 {
678         gboolean ret_value;
679
680         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
681
682 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
683 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
684 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
685 /*              gboolean ret_value; */
686 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
687 /*      } else if (MODEST_IS_WINDOW (win)) { */
688 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
689 /*      } else { */
690 /*              g_return_if_reached (); */
691 /*      } */
692 }
693
694 void
695 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
696 {
697         GtkClipboard *clipboard = NULL;
698         gchar *selection = NULL;
699
700         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
701         selection = gtk_clipboard_wait_for_text (clipboard);
702
703         /* Question: why is the clipboard being used here? 
704          * It doesn't really make a lot of sense. */
705
706         if (selection)
707         {
708                 modest_address_book_add_address (selection);
709                 g_free (selection);
710         }
711 }
712
713 void
714 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
715 {
716         /* This is currently only implemented for Maemo */
717 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
718         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
719                 modest_run_account_setup_wizard (win);
720                 return;
721         } else  {
722                 /* Show the list of accounts: */
723                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
724                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW (win));
725                 
726                 /* The accounts dialog must be modal  */
727                 gtk_window_set_modal (GTK_WINDOW (account_win), TRUE);
728                 modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), account_win); 
729         }
730 #else
731         GtkWidget *dialog, *label;
732         
733         /* Create the widgets */
734         
735         dialog = gtk_dialog_new_with_buttons ("Message",
736                                               GTK_WINDOW(win),
737                                               GTK_DIALOG_DESTROY_WITH_PARENT,
738                                               GTK_STOCK_OK,
739                                               GTK_RESPONSE_NONE,
740                                               NULL);
741         label = gtk_label_new ("Hello World!");
742         
743         /* Ensure that the dialog box is destroyed when the user responds. */
744         
745         g_signal_connect_swapped (dialog, "response", 
746                                   G_CALLBACK (gtk_widget_destroy),
747                                   dialog);
748         
749         /* Add the label, and show everything we've added to the dialog. */
750         
751         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
752                            label);
753         gtk_widget_show_all (dialog);
754 #endif /* MODEST_PLATFORM_MAEMO */
755 }
756
757 static void
758 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
759 {
760         /* Save any changes. */
761         modest_connection_specific_smtp_window_save_server_accounts (
762                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
763         gtk_widget_destroy (GTK_WIDGET (window));
764 }
765
766
767
768 void
769 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
770 {
771         /* This is currently only implemented for Maemo,
772          * because it requires an API (libconic) to detect different connection 
773          * possiblities.
774          */
775 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
776         
777         /* Create the window if necessary: */
778         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
779         modest_connection_specific_smtp_window_fill_with_connections (
780                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
781                 modest_runtime_get_account_mgr());
782
783         /* Show the window: */  
784         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
785         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
786         gtk_widget_show (specific_window);
787     
788         /* Save changes when the window is hidden: */
789         g_signal_connect (specific_window, "hide", 
790                 G_CALLBACK (on_smtp_servers_window_hide), win);
791 #endif /* MODEST_PLATFORM_MAEMO */
792 }
793
794 void
795 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
796 {
797         ModestWindow *msg_win = NULL;
798         TnyMsg *msg = NULL;
799         TnyFolder *folder = NULL;
800         gchar *account_name = NULL;
801         gchar *from_str = NULL;
802 /*      GError *err = NULL; */
803         TnyAccount *account = NULL;
804         ModestWindowMgr *mgr;
805         gchar *signature = NULL, *blank_and_signature = NULL;
806
807         /* if there are no accounts yet, just show the wizard */
808         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
809                         const gboolean created = modest_run_account_setup_wizard (win);
810                         if (!created)
811                                 return;
812         }
813         
814         account_name = g_strdup (modest_window_get_active_account (win));
815         if (!account_name)
816                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
817         if (!account_name) {
818                 g_printerr ("modest: no account found\n");
819                 goto cleanup;
820         }
821         
822         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
823                                                                        account_name,
824                                                                        TNY_ACCOUNT_TYPE_STORE);
825         if (!account) {
826                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
827                 goto cleanup;
828         }
829
830         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
831         if (!from_str) {
832                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
833                 goto cleanup;
834         }
835
836         gboolean use_signature = FALSE;
837         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr (), account_name, &use_signature);
838
839         if (use_signature) {
840                 blank_and_signature = g_strconcat ("\n", signature, NULL);
841         } else {
842                 blank_and_signature = g_strdup ("");
843         }
844
845         g_free (signature);
846
847         msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
848         if (!msg) {
849                 g_printerr ("modest: failed to create new msg\n");
850                 goto cleanup;
851         }
852         
853         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
854         if (!folder) {
855                 g_printerr ("modest: failed to find Drafts folder\n");
856                 goto cleanup;
857         }
858         
859         
860         /* Create and register edit window */
861         /* This is destroyed by TODO. */
862         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
863         mgr = modest_runtime_get_window_mgr ();
864         modest_window_mgr_register_window (mgr, msg_win);
865
866         if (win)
867                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
868                                               GTK_WINDOW (win));
869         gtk_widget_show_all (GTK_WIDGET (msg_win));
870
871 cleanup:
872         g_free (account_name);
873         g_free (from_str);
874         g_free (blank_and_signature);
875         if (msg_win)
876                 g_object_unref (msg_win);
877         if (account)
878                 g_object_unref (G_OBJECT(account));
879         if (msg)
880                 g_object_unref (G_OBJECT(msg));
881         if (folder)
882                 g_object_unref (G_OBJECT(folder));
883 }
884
885 gboolean 
886 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
887                                        TnyHeader *header,
888                                        TnyMsg *msg)
889 {
890         ModestMailOperationStatus status;
891
892         /* If there is no message or the operation was not successful */
893         status = modest_mail_operation_get_status (mail_op);
894         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
895
896                 /* Remove the header from the preregistered uids */
897                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
898                                                      header);
899
900                 return FALSE;
901         }
902
903         return TRUE;
904 }
905
906 static void
907 open_msg_cb (ModestMailOperation *mail_op, TnyHeader *header,  TnyMsg *msg, gpointer user_data)
908 {
909         ModestWindowMgr *mgr = NULL;
910         ModestWindow *parent_win = NULL;
911         ModestWindow *win = NULL;
912         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
913         gchar *account = NULL;
914         TnyFolder *folder;
915         
916         /* Do nothing if there was any problem with the mail
917            operation. The error will be shown by the error_handler of
918            the mail operation */
919         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
920                 return;
921
922         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
923         folder = tny_header_get_folder (header);
924
925         /* Mark header as read */
926         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
927
928         /* Get account */
929         account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
930         if (!account)
931                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
932         
933         /* Gets folder type (OUTBOX headers will be opened in edit window */
934         if (modest_tny_folder_is_local_folder (folder))
935                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
936
937         /* If the header is in the drafts folder then open the editor,
938            else the message view window */
939         if ((folder_type == TNY_FOLDER_TYPE_DRAFTS) ||
940             (folder_type == TNY_FOLDER_TYPE_OUTBOX)) {
941                 /* we cannot edit without a valid account... */
942                 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
943                         const gboolean created = modest_run_account_setup_wizard(parent_win);
944                         if (!created)
945                                 goto cleanup;
946                 }
947                 win = modest_msg_edit_window_new (msg, account, TRUE);
948
949
950                 /* Show banner */
951                 modest_platform_information_banner (NULL, NULL, _("mail_ib_opening_draft_message"));
952
953         } else {
954                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
955                 
956                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
957                         GtkWidget *header_view;
958                         GtkTreeSelection *sel;
959                         GList *sel_list = NULL;
960                         GtkTreeModel *model;
961                         
962                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
963                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
964
965                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
966                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
967
968                         if (sel_list != NULL) {
969                                 GtkTreeRowReference *row_reference;
970
971                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
972                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
973                                 g_list_free (sel_list);
974                                 
975                                 win = modest_msg_view_window_new_with_header_model (
976                                                 msg, account, (const gchar*) uid,
977                                                 model, row_reference);
978                                 gtk_tree_row_reference_free (row_reference);
979                         } else {
980                                 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
981                         }
982                 } else {
983                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
984                 }
985                 g_free (uid);
986         }
987         
988         /* Register and show new window */
989         if (win != NULL) {
990                 mgr = modest_runtime_get_window_mgr ();
991                 modest_window_mgr_register_window (mgr, win);
992                 g_object_unref (win);
993                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
994                 gtk_widget_show_all (GTK_WIDGET(win));
995         }
996
997         /* Update toolbar dimming state */
998         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
999                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1000         }
1001
1002 cleanup:
1003         /* Free */
1004         g_free(account);
1005         g_object_unref (parent_win);
1006         g_object_unref (folder);
1007 }
1008
1009 void
1010 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
1011                                                gpointer user_data)
1012 {
1013         const GError *error;
1014         GObject *win = modest_mail_operation_get_source (mail_op);
1015
1016         error = modest_mail_operation_get_error (mail_op);
1017 /*      printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, error->code, error->message); */
1018  
1019         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
1020
1021                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1022                                                         error->message);
1023         } else {
1024                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1025                                                         _("mail_ni_ui_folder_get_msg_folder_error"));
1026         }
1027
1028         if (win)
1029                 g_object_unref (win);
1030 }
1031
1032 /*
1033  * This function is used by both modest_ui_actions_on_open and
1034  * modest_ui_actions_on_header_activated. This way we always do the
1035  * same when trying to open messages.
1036  */
1037 static void
1038 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
1039 {
1040         ModestWindowMgr *mgr = NULL;
1041         TnyIterator *iter = NULL;
1042         ModestMailOperation *mail_op = NULL;
1043         TnyList *not_opened_headers = NULL;
1044         TnyHeaderFlags flags = 0;
1045                 
1046         g_return_if_fail (headers != NULL);
1047
1048         /* Check that only one message is selected for opening */
1049         if (tny_list_get_length (headers) != 1) {
1050                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1051                                                         _("mcen_ib_select_one_message"));
1052                 return;
1053         }
1054
1055
1056         /* Look if we already have a message view for each header. If
1057            true, then remove the header from the list of headers to
1058            open */
1059         mgr = modest_runtime_get_window_mgr ();
1060         iter = tny_list_create_iterator (headers);
1061         not_opened_headers = tny_simple_list_new ();
1062         
1063         while (!tny_iterator_is_done (iter)) {
1064
1065                 ModestWindow *window = NULL;
1066                 TnyHeader *header = NULL;
1067                 gboolean found = FALSE;
1068                 
1069                 header = TNY_HEADER (tny_iterator_get_current (iter));
1070                 if (header)
1071                         flags = tny_header_get_flags (header);
1072
1073                 window = NULL;
1074                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1075                 
1076                 /* Do not open again the message and present the
1077                    window to the user */
1078                 if (found) {
1079                         if (window)
1080                                 gtk_window_present (GTK_WINDOW (window));
1081                         else
1082                                 /* the header has been registered already, we don't do
1083                                  * anything but wait for the window to come up*/
1084                                 g_debug ("header %p already registered, waiting for window", header);
1085                 } else {
1086                         tny_list_append (not_opened_headers, G_OBJECT (header));
1087                 }
1088
1089                 if (header)
1090                         g_object_unref (header);
1091
1092                 tny_iterator_next (iter);
1093         }
1094         g_object_unref (iter);
1095         iter = NULL;
1096         
1097         /* If some messages would have to be downloaded, ask the user to 
1098          * make a connection. It's generally easier to do this here (in the mainloop) 
1099          * than later in a thread:
1100          */
1101         if (tny_list_get_length (not_opened_headers) > 0) {
1102                 TnyIterator *iter;
1103                 gboolean found = FALSE;
1104
1105                 iter = tny_list_create_iterator (not_opened_headers);
1106                 while (!tny_iterator_is_done (iter) && !found) {
1107                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1108                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1109                                 found = TRUE;
1110                         else
1111                                 tny_iterator_next (iter);
1112
1113                         g_object_unref (header);
1114                 }
1115                 g_object_unref (iter);
1116
1117                 if (found && !modest_platform_connect_and_wait (GTK_WINDOW (win), NULL)) {
1118                         g_object_unref (not_opened_headers);
1119                         return;                 
1120                 }
1121         }
1122         
1123         /* Register the headers before actually creating the windows: */
1124         TnyIterator *iter_not_opened = tny_list_create_iterator (not_opened_headers);
1125         while (!tny_iterator_is_done (iter_not_opened)) {
1126                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1127                 if (header) {
1128                         modest_window_mgr_register_header (mgr, header);
1129                         g_object_unref (header);
1130                 }
1131                 
1132                 tny_iterator_next (iter_not_opened);
1133         }
1134         g_object_unref (iter_not_opened);
1135         iter_not_opened = NULL;
1136         
1137         /* Open each message */
1138         if (tny_list_get_length (not_opened_headers) > 0) {
1139                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1140                                                                          G_OBJECT (win), 
1141                                                                          modest_ui_actions_get_msgs_full_error_handler, 
1142                                                                          NULL);
1143                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1144                 if (tny_list_get_length (not_opened_headers) > 1) {
1145                         modest_mail_operation_get_msgs_full (mail_op, 
1146                                                              not_opened_headers, 
1147                                                              open_msg_cb, 
1148                                                              NULL, 
1149                                                              NULL);
1150                 } else {
1151                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1152                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1153                         modest_mail_operation_get_msg (mail_op, header, open_msg_cb, NULL);
1154                         g_object_unref (header);
1155                         g_object_unref (iter);
1156                 }
1157                 g_object_unref (mail_op);
1158         }
1159
1160         /* Clean */
1161         if (not_opened_headers != NULL)
1162                 g_object_unref (not_opened_headers);
1163 }
1164
1165 void
1166 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1167 {
1168         TnyList *headers;
1169
1170         /* Get headers */
1171         headers = get_selected_headers (win);
1172         if (!headers)
1173                 return;
1174
1175         /* Open them */
1176         _modest_ui_actions_open (headers, win);
1177
1178         g_object_unref(headers);
1179 }
1180
1181
1182 static void
1183 free_reply_forward_helper (gpointer data)
1184 {
1185         ReplyForwardHelper *helper;
1186
1187         helper = (ReplyForwardHelper *) data;
1188         g_free (helper->account_name);
1189         g_slice_free (ReplyForwardHelper, helper);
1190 }
1191
1192 static void
1193 reply_forward_cb (ModestMailOperation *mail_op,  TnyHeader *header, TnyMsg *msg,
1194                   gpointer user_data)
1195 {
1196         TnyMsg *new_msg;
1197         ReplyForwardHelper *rf_helper;
1198         ModestWindow *msg_win = NULL;
1199         ModestEditType edit_type;
1200         gchar *from = NULL;
1201         TnyAccount *account = NULL;
1202         ModestWindowMgr *mgr = NULL;
1203         gchar *signature = NULL;
1204         gboolean use_signature;
1205
1206         /* If there was any error. The mail operation could be NULL,
1207            this means that we already have the message downloaded and
1208            that we didn't do a mail operation to retrieve it */
1209         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1210                 return;
1211                         
1212         g_return_if_fail (user_data != NULL);
1213         rf_helper = (ReplyForwardHelper *) user_data;
1214
1215         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1216                                                    rf_helper->account_name);
1217         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(), 
1218                                                       rf_helper->account_name, 
1219                                                       &use_signature);
1220
1221         /* Create reply mail */
1222         switch (rf_helper->action) {
1223         case ACTION_REPLY:
1224                 new_msg = 
1225                         modest_tny_msg_create_reply_msg (msg, header, from, signature,
1226                                                          rf_helper->reply_forward_type,
1227                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1228                 break;
1229         case ACTION_REPLY_TO_ALL:
1230                 new_msg = 
1231                         modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1232                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1233                 edit_type = MODEST_EDIT_TYPE_REPLY;
1234                 break;
1235         case ACTION_FORWARD:
1236                 new_msg = 
1237                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1238                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1239                 break;
1240         default:
1241                 g_return_if_reached ();
1242                 return;
1243         }
1244
1245         g_free (signature);
1246
1247         if (!new_msg) {
1248                 g_printerr ("modest: failed to create message\n");
1249                 goto cleanup;
1250         }
1251
1252         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1253                                                                        rf_helper->account_name,
1254                                                                        TNY_ACCOUNT_TYPE_STORE);
1255         if (!account) {
1256                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1257                 goto cleanup;
1258         }
1259
1260         /* Create and register the windows */
1261         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1262         mgr = modest_runtime_get_window_mgr ();
1263         modest_window_mgr_register_window (mgr, msg_win);
1264
1265         if (rf_helper->parent_window != NULL) {
1266                 gdouble parent_zoom;
1267
1268                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1269                 modest_window_set_zoom (msg_win, parent_zoom);
1270         }
1271
1272         /* Show edit window */
1273         gtk_widget_show_all (GTK_WIDGET (msg_win));
1274
1275 cleanup:
1276         if (msg_win)
1277                 g_object_unref (msg_win);
1278         if (new_msg)
1279                 g_object_unref (G_OBJECT (new_msg));
1280         if (account)
1281                 g_object_unref (G_OBJECT (account));
1282 /*      g_object_unref (msg); */
1283         free_reply_forward_helper (rf_helper);
1284 }
1285
1286 /* Checks a list of headers. If any of them are not currently
1287  * downloaded (CACHED) then returns TRUE else returns FALSE.
1288  */
1289 static gint
1290 header_list_count_uncached_msgs (TnyList *header_list)
1291 {
1292         TnyIterator *iter;
1293         gint uncached_messages = 0;
1294
1295         iter = tny_list_create_iterator (header_list);
1296         while (!tny_iterator_is_done (iter)) {
1297                 TnyHeader *header;
1298
1299                 header = TNY_HEADER (tny_iterator_get_current (iter));
1300                 if (header) {
1301                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1302                                 uncached_messages ++;
1303                         g_object_unref (header);
1304                 }
1305
1306                 tny_iterator_next (iter);
1307         }
1308         g_object_unref (iter);
1309
1310         return uncached_messages;
1311 }
1312
1313 /* Returns FALSE if the user does not want to download the
1314  * messages. Returns TRUE if the user allowed the download.
1315  */
1316 static gboolean
1317 connect_to_get_msg (GtkWindow *win,
1318                     gint num_of_uncached_msgs)
1319 {
1320         /* Allways download if we are online. */
1321         if (tny_device_is_online (modest_runtime_get_device ()))
1322                 return TRUE;
1323
1324         /* If offline, then ask for user permission to download the messages */
1325         GtkResponseType response;
1326         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1327                         ngettext("mcen_nc_get_msg",
1328                         "mcen_nc_get_msgs",
1329                         num_of_uncached_msgs));
1330         if (response == GTK_RESPONSE_CANCEL)
1331                 return FALSE;
1332
1333         return modest_platform_connect_and_wait(win, NULL);     
1334 }
1335
1336 /*
1337  * Common code for the reply and forward actions
1338  */
1339 static void
1340 reply_forward (ReplyForwardAction action, ModestWindow *win)
1341 {
1342         ModestMailOperation *mail_op = NULL;
1343         TnyList *header_list = NULL;
1344         ReplyForwardHelper *rf_helper = NULL;
1345         guint reply_forward_type;
1346         gboolean continue_download = TRUE;
1347         gboolean do_retrieve = TRUE;
1348         
1349         g_return_if_fail (MODEST_IS_WINDOW(win));
1350
1351         /* we need an account when editing */
1352         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1353                 const gboolean created = modest_run_account_setup_wizard (win);
1354                 if (!created)
1355                         return;
1356         }
1357         
1358         header_list = get_selected_headers (win);
1359         if (!header_list)
1360                 return;
1361
1362         reply_forward_type = 
1363                 modest_conf_get_int (modest_runtime_get_conf (),
1364                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1365                                      NULL);
1366
1367         /* check if we need to download msg before asking about it */
1368         do_retrieve = (action == ACTION_FORWARD) ||
1369                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1370
1371         if (do_retrieve){
1372                 gint num_of_unc_msgs;
1373                 /* check that the messages have been previously downloaded */
1374                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1375                 /* If there are any uncached message ask the user
1376                  * whether he/she wants to download them. */
1377                 if (num_of_unc_msgs)
1378                         continue_download = connect_to_get_msg (
1379                                                                 GTK_WINDOW (win),
1380                                                                 num_of_unc_msgs);
1381         }
1382
1383         if (!continue_download) {
1384                 g_object_unref (header_list);
1385                 return;
1386         }
1387         
1388         /* We assume that we can only select messages of the
1389            same folder and that we reply all of them from the
1390            same account. In fact the interface currently only
1391            allows single selection */
1392         
1393         /* Fill helpers */
1394         rf_helper = g_slice_new0 (ReplyForwardHelper);
1395         rf_helper->reply_forward_type = reply_forward_type;
1396         rf_helper->action = action;
1397         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1398         
1399         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1400                 rf_helper->parent_window = GTK_WIDGET (win);
1401         if (!rf_helper->account_name)
1402                 rf_helper->account_name =
1403                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1404
1405         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1406                 TnyMsg *msg;
1407                 TnyHeader *header;
1408                 /* Get header and message. Do not free them here, the
1409                    reply_forward_cb must do it */
1410                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1411                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1412                 if (!msg || !header) {
1413                         if (msg)
1414                                 g_object_unref (msg);
1415                         g_printerr ("modest: no message found\n");
1416                         return;
1417                 } else {
1418                         reply_forward_cb (NULL, header, msg, rf_helper);
1419                 }
1420                 if (header)
1421                         g_object_unref (header);
1422         } else {
1423                 TnyHeader *header;
1424                 TnyIterator *iter;
1425
1426                 /* Only reply/forward to one message */
1427                 iter = tny_list_create_iterator (header_list);
1428                 header = TNY_HEADER (tny_iterator_get_current (iter));
1429                 g_object_unref (iter);
1430
1431                 if (header) {
1432                         /* Retrieve messages */
1433                         if (do_retrieve) {
1434                                 mail_op = modest_mail_operation_new_with_error_handling (
1435                                         MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1436                                         G_OBJECT(win),
1437                                         modest_ui_actions_get_msgs_full_error_handler, 
1438                                         NULL);
1439                                 modest_mail_operation_queue_add (
1440                                         modest_runtime_get_mail_operation_queue (), mail_op);
1441                                 
1442                                 modest_mail_operation_get_msg (mail_op,
1443                                                                header,
1444                                                                reply_forward_cb,
1445                                                                rf_helper);
1446                                 /* Clean */
1447                                 g_object_unref(mail_op);
1448                         } else {
1449                                 /* we put a ref here to prevent double unref as the reply
1450                                  * forward callback unrefs the header at its end */
1451                                 reply_forward_cb (NULL, header, NULL, rf_helper);
1452                         }
1453
1454
1455                         g_object_unref (header);
1456                 }
1457
1458         }
1459
1460         /* Free */
1461         g_object_unref (header_list);
1462 }
1463
1464 void
1465 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1466 {
1467         g_return_if_fail (MODEST_IS_WINDOW(win));
1468
1469         reply_forward (ACTION_REPLY, win);
1470 }
1471
1472 void
1473 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1474 {
1475         g_return_if_fail (MODEST_IS_WINDOW(win));
1476
1477         reply_forward (ACTION_FORWARD, win);
1478 }
1479
1480 void
1481 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1482 {
1483         g_return_if_fail (MODEST_IS_WINDOW(win));
1484
1485         reply_forward (ACTION_REPLY_TO_ALL, win);
1486 }
1487
1488 void 
1489 modest_ui_actions_on_next (GtkAction *action, 
1490                            ModestWindow *window)
1491 {
1492         if (MODEST_IS_MAIN_WINDOW (window)) {
1493                 GtkWidget *header_view;
1494
1495                 header_view = modest_main_window_get_child_widget (
1496                                 MODEST_MAIN_WINDOW(window),
1497                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1498                 if (!header_view)
1499                         return;
1500         
1501                 modest_header_view_select_next (
1502                                 MODEST_HEADER_VIEW(header_view)); 
1503         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1504                 modest_msg_view_window_select_next_message (
1505                                 MODEST_MSG_VIEW_WINDOW (window));
1506         } else {
1507                 g_return_if_reached ();
1508         }
1509 }
1510
1511 void 
1512 modest_ui_actions_on_prev (GtkAction *action, 
1513                            ModestWindow *window)
1514 {
1515         g_return_if_fail (MODEST_IS_WINDOW(window));
1516
1517         if (MODEST_IS_MAIN_WINDOW (window)) {
1518                 GtkWidget *header_view;
1519                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1520                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1521                 if (!header_view)
1522                         return;
1523                 
1524                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1525         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1526                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1527         } else {
1528                 g_return_if_reached ();
1529         }
1530 }
1531
1532 void 
1533 modest_ui_actions_on_sort (GtkAction *action, 
1534                            ModestWindow *window)
1535 {
1536         g_return_if_fail (MODEST_IS_WINDOW(window));
1537
1538         if (MODEST_IS_MAIN_WINDOW (window)) {
1539                 GtkWidget *header_view;
1540                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1541                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1542                 if (!header_view) {
1543                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1544
1545                         return;
1546                 }
1547
1548                 /* Show sorting dialog */
1549                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1550         }
1551 }
1552
1553 static void
1554 new_messages_arrived (ModestMailOperation *self, 
1555                       TnyList *new_headers,
1556                       gpointer user_data)
1557 {
1558         ModestMainWindow *win = NULL;
1559         GtkWidget *folder_view = NULL;
1560         TnyFolderStore *folder = NULL;
1561         gboolean folder_empty = FALSE;
1562
1563         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
1564         win = MODEST_MAIN_WINDOW (user_data);
1565
1566         /* Don't do anything if there are not new headers, this could
1567            happen if there was any problem with the mail operation */
1568         if (!new_headers)
1569                 return;
1570
1571         /* Set contents style of headers view */
1572         if (modest_main_window_get_contents_style (win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1573                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1574                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1575                 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));             
1576                 
1577
1578                 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1579                 
1580                 if (!folder_empty)
1581                         modest_main_window_set_contents_style (win,
1582                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1583         }       
1584
1585         /* Notify new messages have been downloaded */
1586         if ((new_headers != NULL) && (tny_list_get_length (new_headers) > 0)) {
1587                 TnyIterator *iter = tny_list_create_iterator (new_headers);
1588                 do {
1589                         TnyHeader *header =  NULL;
1590
1591                         header = TNY_HEADER (tny_iterator_get_current (iter));
1592                         modest_platform_on_new_header_received (header);
1593                         g_object_unref (header);
1594
1595                         tny_iterator_next (iter);
1596                 } while (!tny_iterator_is_done (iter));
1597                 g_object_unref (iter);
1598         }
1599 }
1600
1601 /*
1602  * This function performs the send & receive required actions. The
1603  * window is used to create the mail operation. Typically it should
1604  * always be the main window, but we pass it as argument in order to
1605  * be more flexible.
1606  */
1607 void
1608 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1609 {
1610         gchar *acc_name = NULL;
1611         ModestMailOperation *mail_op;
1612         TnyAccount *store_account = NULL;
1613
1614         /* If no account name was provided then get the current account, and if
1615            there is no current account then pick the default one: */
1616         if (!account_name) {
1617                 acc_name = g_strdup (modest_window_get_active_account(win));
1618                 if (!acc_name)
1619                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1620                 if (!acc_name) {
1621                         g_printerr ("modest: cannot get default account\n");
1622                         return;
1623                 }
1624         } else {
1625                 acc_name = g_strdup (account_name);
1626         }
1627
1628
1629         /* Ensure that we have a connection available */
1630         store_account =
1631                 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1632                                                              acc_name,
1633                                                              TNY_ACCOUNT_TYPE_STORE);
1634         if (!modest_platform_connect_and_wait (NULL, TNY_ACCOUNT (store_account))) {
1635                 g_object_unref (store_account);
1636                 return;
1637         }
1638         g_object_unref (store_account);
1639
1640         /* Set send/receive operation in progress */    
1641         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1642
1643         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1644                                                                  G_OBJECT (win),
1645                                                                  modest_ui_actions_send_receive_error_handler,
1646                                                                  NULL);
1647
1648         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1649                           G_CALLBACK (_on_send_receive_progress_changed), 
1650                           win);
1651
1652         /* Send & receive. */
1653         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1654         /* Receive and then send. The operation is tagged initially as
1655            a receive operation because the account update performs a
1656            receive and then a send. The operation changes its type
1657            internally, so the progress objects will receive the proper
1658            progress information */
1659         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1660         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, win);
1661         g_object_unref (G_OBJECT (mail_op));
1662         
1663         /* Free */
1664         g_free (acc_name);
1665 }
1666
1667
1668 static void
1669 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1670                                   ModestWindow *win)
1671 {
1672         TnyTransportAccount *transport_account;
1673         TnySendQueue *send_queue = NULL;
1674         GError *error = NULL;
1675
1676         /* Get transport account */
1677         transport_account =
1678                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1679                                       (modest_runtime_get_account_store(),
1680                                        account_name,
1681                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1682         if (!transport_account) {
1683                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1684                 goto frees;
1685         }
1686
1687         /* Get send queue*/
1688         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1689         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1690                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1691                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1692                              "modest: could not find send queue for account\n");
1693         } else {
1694                 /* Keeep messages in outbox folder */
1695                 tny_send_queue_cancel (send_queue, FALSE, &error);
1696         }       
1697
1698  frees:
1699         if (transport_account != NULL) 
1700                 g_object_unref (G_OBJECT (transport_account));
1701 }
1702
1703 static void
1704 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1705 {
1706         GSList *account_names, *iter;
1707
1708         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1709                                                           TRUE);
1710
1711         iter = account_names;
1712         while (iter) {                  
1713                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1714                 iter = g_slist_next (iter);
1715         }
1716
1717         modest_account_mgr_free_account_names (account_names);
1718         account_names = NULL;
1719 }
1720
1721 void
1722 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1723
1724 {
1725         /* Check if accounts exist */
1726         gboolean accounts_exist = 
1727                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1728         
1729         /* If not, allow the user to create an account before trying to send/receive. */
1730         if (!accounts_exist)
1731                 modest_ui_actions_on_accounts (NULL, win);
1732         
1733         /* Cancel all sending operaitons */     
1734         modest_ui_actions_cancel_send_all (win);
1735 }
1736
1737 /*
1738  * Refreshes all accounts. This function will be used by automatic
1739  * updates
1740  */
1741 void
1742 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1743 {
1744         GSList *account_names, *iter;
1745
1746         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1747                                                           TRUE);
1748
1749         iter = account_names;
1750         while (iter) {                  
1751                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1752                 iter = g_slist_next (iter);
1753         }
1754
1755         modest_account_mgr_free_account_names (account_names);
1756         account_names = NULL;
1757 }
1758
1759 void 
1760 modest_do_refresh_current_folder(ModestWindow *win)
1761 {
1762         /* Refresh currently selected folder. Note that if we only
1763            want to retreive the headers, then the refresh only will
1764            invoke a poke_status over all folders, i.e., only the
1765            total/unread count will be updated */
1766         if (MODEST_IS_MAIN_WINDOW (win)) {
1767                 GtkWidget *header_view, *folder_view;
1768                 TnyFolderStore *folder_store;
1769
1770                 /* Get folder and header view */
1771                 folder_view = 
1772                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1773                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1774                 if (!folder_view)
1775                         return;
1776
1777                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1778
1779                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1780                         header_view = 
1781                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1782                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1783                 
1784                         /* We do not need to set the contents style
1785                            because it hasn't changed. We also do not
1786                            need to save the widget status. Just force
1787                            a refresh */
1788                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1789                                                        TNY_FOLDER (folder_store),
1790                                                        folder_refreshed_cb,
1791                                                        MODEST_MAIN_WINDOW (win));
1792                 }
1793                 
1794                 if (folder_store)
1795                         g_object_unref (folder_store);
1796         }
1797 }
1798
1799
1800 /*
1801  * Handler of the click on Send&Receive button in the main toolbar
1802  */
1803 void
1804 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1805 {
1806         /* Check if accounts exist */
1807         gboolean accounts_exist = 
1808                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1809         
1810         /* If not, allow the user to create an account before trying to send/receive. */
1811         if (!accounts_exist)
1812                 modest_ui_actions_on_accounts (NULL, win);
1813
1814         modest_do_refresh_current_folder (win);
1815         
1816         /* Refresh the active account */
1817         modest_ui_actions_do_send_receive (NULL, win);
1818 }
1819
1820
1821 void
1822 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1823 {
1824         ModestConf *conf;
1825         GtkWidget *header_view;
1826         
1827         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1828
1829         header_view = modest_main_window_get_child_widget (main_window,
1830                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1831         if (!header_view)
1832                 return;
1833
1834         conf = modest_runtime_get_conf ();
1835         
1836         /* what is saved/restored is depending on the style; thus; we save with
1837          * old style, then update the style, and restore for this new style
1838          */
1839         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1840         
1841         if (modest_header_view_get_style
1842             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1843                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1844                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1845         else
1846                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1847                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1848
1849         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1850                                       MODEST_CONF_HEADER_VIEW_KEY);
1851 }
1852
1853
1854 void 
1855 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1856                                       TnyHeader *header,
1857                                       ModestMainWindow *main_window)
1858 {
1859         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1860         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1861         
1862         /* in the case the folder is empty, show the empty folder message and focus
1863          * folder view */
1864         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1865                 if (modest_header_view_is_empty (header_view)) {
1866                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1867                         GtkWidget *folder_view = 
1868                                 modest_main_window_get_child_widget (main_window,
1869                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1870                         if (folder != NULL) 
1871                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1872                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1873                         return;
1874                 }
1875         }
1876         /* If no header has been selected then exit */
1877         if (!header)
1878                 return;
1879
1880         /* Update focus */
1881         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1882             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1883
1884         /* Update toolbar dimming state */
1885         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1886 }
1887
1888 void
1889 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1890                                        TnyHeader *header,
1891                                        ModestMainWindow *main_window)
1892 {
1893         TnyList *headers;
1894
1895         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1896         
1897         if (!header)
1898                 return;
1899
1900         if (modest_header_view_count_selected_headers (header_view) > 1) {
1901                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1902                 return;
1903         }
1904
1905
1906 /*      headers = tny_simple_list_new (); */
1907 /*      tny_list_prepend (headers, G_OBJECT (header)); */
1908         headers = modest_header_view_get_selected_headers (header_view);
1909
1910         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1911
1912         g_object_unref (headers);
1913 }
1914
1915 static void
1916 set_active_account_from_tny_account (TnyAccount *account,
1917                                      ModestWindow *window)
1918 {
1919         const gchar *server_acc_name = tny_account_get_id (account);
1920         
1921         /* We need the TnyAccount provided by the
1922            account store because that is the one that
1923            knows the name of the Modest account */
1924         TnyAccount *modest_server_account = modest_server_account = 
1925                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1926                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1927                                                              server_acc_name);
1928         if (!modest_server_account) {
1929                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
1930                 return;
1931         }
1932
1933         /* Update active account, but only if it's not a pseudo-account */
1934         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
1935             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
1936                 const gchar *modest_acc_name = 
1937                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1938                 if (modest_acc_name)
1939                         modest_window_set_active_account (window, modest_acc_name);
1940         }
1941         
1942         g_object_unref (modest_server_account);
1943 }
1944
1945
1946 static void
1947 folder_refreshed_cb (ModestMailOperation *mail_op, 
1948                      TnyFolder *folder, 
1949                      gpointer user_data)
1950 {
1951         ModestMainWindow *win = NULL;
1952         GtkWidget *header_view;
1953         gboolean folder_empty = FALSE;
1954         gboolean all_marked_as_deleted = FALSE;
1955
1956         g_return_if_fail (TNY_IS_FOLDER (folder));
1957
1958         win = MODEST_MAIN_WINDOW (user_data);
1959         header_view = 
1960                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1961
1962         if (header_view) {
1963                 TnyFolder *current_folder;
1964
1965                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
1966                 if (current_folder != NULL && folder != current_folder) {
1967                         g_object_unref (current_folder);
1968                         return;
1969                 }
1970                 g_object_unref (current_folder);
1971         }
1972
1973         /* Check if folder is empty and set headers view contents style */
1974         folder_empty = (tny_folder_get_all_count (folder) == 0);
1975         all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
1976         if (folder_empty || all_marked_as_deleted)
1977                 modest_main_window_set_contents_style (win,
1978                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1979 }
1980
1981 void 
1982 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1983                                                TnyFolderStore *folder_store, 
1984                                                gboolean selected,
1985                                                ModestMainWindow *main_window)
1986 {
1987         ModestConf *conf;
1988         GtkWidget *header_view;
1989
1990         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1991
1992         header_view = modest_main_window_get_child_widget(main_window,
1993                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1994         if (!header_view)
1995                 return;
1996         
1997         conf = modest_runtime_get_conf ();
1998
1999         if (TNY_IS_ACCOUNT (folder_store)) {
2000                 if (selected) {
2001                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2002                         
2003                         /* Show account details */
2004                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2005                 }
2006         } else {
2007                 if (TNY_IS_FOLDER (folder_store) && selected) {
2008                         
2009                         /* Update the active account */
2010                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2011                         if (account) {
2012                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2013                                 g_object_unref (account);
2014                                 account = NULL;
2015                         }
2016
2017                         /* Set the header style by default, it could
2018                            be changed later by the refresh callback to
2019                            empty */
2020                         modest_main_window_set_contents_style (main_window, 
2021                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2022
2023                         /* Set folder on header view. This function
2024                            will call tny_folder_refresh_async so we
2025                            pass a callback that will be called when
2026                            finished. We use that callback to set the
2027                            empty view if there are no messages */
2028                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2029                                                        TNY_FOLDER (folder_store),
2030                                                        folder_refreshed_cb,
2031                                                        main_window);
2032                         
2033                         /* Restore configuration. We need to do this
2034                            *after* the set_folder because the widget
2035                            memory asks the header view about its
2036                            folder  */
2037                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2038                                                       G_OBJECT(header_view),
2039                                                       MODEST_CONF_HEADER_VIEW_KEY);
2040                 } else {
2041                         /* Update the active account */
2042                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2043                         /* Save only if we're seeing headers */
2044                         if (modest_main_window_get_contents_style (main_window) ==
2045                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2046                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2047                                                            MODEST_CONF_HEADER_VIEW_KEY);
2048                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2049                 }
2050         }
2051
2052         /* Update toolbar dimming state */
2053         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2054 }
2055
2056 void 
2057 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2058                                      ModestWindow *win)
2059 {
2060         GtkWidget *dialog;
2061         gchar *txt, *item;
2062         gboolean online;
2063
2064         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2065         
2066         online = tny_device_is_online (modest_runtime_get_device());
2067
2068         if (online) {
2069                 /* already online -- the item is simply not there... */
2070                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2071                                                  GTK_DIALOG_MODAL,
2072                                                  GTK_MESSAGE_WARNING,
2073                                                  GTK_BUTTONS_NONE,
2074                                                  _("The %s you selected cannot be found"),
2075                                                  item);
2076                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2077                 gtk_dialog_run (GTK_DIALOG(dialog));
2078         } else {
2079                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2080                                                       GTK_WINDOW (win),
2081                                                       GTK_DIALOG_MODAL,
2082                                                       _("mcen_bd_dialog_cancel"),
2083                                                       GTK_RESPONSE_REJECT,
2084                                                       _("mcen_bd_dialog_ok"),
2085                                                       GTK_RESPONSE_ACCEPT,
2086                                                       NULL);
2087                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2088                                          "Do you want to get online?"), item);
2089                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2090                                     gtk_label_new (txt), FALSE, FALSE, 0);
2091                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2092                 g_free (txt);
2093
2094                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2095                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2096                         /* TODO: Comment about why is this commented out: */
2097                         /* modest_platform_connect_and_wait (); */
2098                 }
2099         }
2100         gtk_widget_destroy (dialog);
2101 }
2102
2103 void
2104 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2105                                      ModestWindow *win)
2106 {
2107         /* g_message ("%s %s", __FUNCTION__, link); */
2108 }       
2109
2110
2111 void
2112 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2113                                         ModestWindow *win)
2114 {
2115         modest_platform_activate_uri (link);
2116 }
2117
2118 void
2119 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2120                                           ModestWindow *win)
2121 {
2122         modest_platform_show_uri_popup (link);
2123 }
2124
2125 void
2126 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2127                                              ModestWindow *win)
2128 {
2129         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2130 }
2131
2132 void
2133 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2134                                           const gchar *address,
2135                                           ModestWindow *win)
2136 {
2137         /* g_message ("%s %s", __FUNCTION__, address); */
2138 }
2139
2140 void
2141 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2142 {
2143         TnyTransportAccount *transport_account;
2144         ModestMailOperation *mail_operation;
2145         MsgData *data;
2146         gchar *account_name, *from;
2147         ModestAccountMgr *account_mgr;
2148         gchar *info_text = NULL;
2149
2150         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2151         
2152         data = modest_msg_edit_window_get_msg_data (edit_window);
2153
2154         account_mgr = modest_runtime_get_account_mgr();
2155         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2156         if (!account_name) 
2157                 account_name = modest_account_mgr_get_default_account (account_mgr);
2158         if (!account_name) {
2159                 g_printerr ("modest: no account found\n");
2160                 modest_msg_edit_window_free_msg_data (edit_window, data);
2161                 return;
2162         }
2163
2164         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2165                 account_name = g_strdup (data->account_name);
2166         }
2167
2168         transport_account =
2169                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2170                                       (modest_runtime_get_account_store(),
2171                                        account_name,
2172                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2173         if (!transport_account) {
2174                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2175                 g_free (account_name);
2176                 modest_msg_edit_window_free_msg_data (edit_window, data);
2177                 return;
2178         }
2179         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2180
2181         /* Create the mail operation */         
2182         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
2183         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2184
2185         modest_mail_operation_save_to_drafts (mail_operation,
2186                                               transport_account,
2187                                               data->draft_msg,
2188                                               edit_window,
2189                                               from,
2190                                               data->to, 
2191                                               data->cc, 
2192                                               data->bcc,
2193                                               data->subject, 
2194                                               data->plain_body, 
2195                                               data->html_body,
2196                                               data->attachments,
2197                                               data->images,
2198                                               data->priority_flags);
2199         /* Frees */
2200         g_free (from);
2201         g_free (account_name);
2202         g_object_unref (G_OBJECT (transport_account));
2203         g_object_unref (G_OBJECT (mail_operation));
2204
2205         modest_msg_edit_window_free_msg_data (edit_window, data);
2206
2207         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2208         modest_platform_information_banner (NULL, NULL, info_text);
2209         modest_msg_edit_window_reset_modified (edit_window);
2210         g_free (info_text);
2211 }
2212
2213 /* For instance, when clicking the Send toolbar button when editing a message: */
2214 void
2215 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2216 {
2217         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2218
2219         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2220                 return;
2221         
2222         /* Offer the connection dialog, if necessary: */        
2223         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window), NULL))
2224                 return;
2225         
2226         /* FIXME: Code added just for testing. The final version will
2227            use the send queue provided by tinymail and some
2228            classifier */
2229         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2230         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2231         if (!account_name) 
2232                 account_name = modest_account_mgr_get_default_account (account_mgr);
2233                 
2234         if (!account_name) {
2235                 /* Run account setup wizard */
2236                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2237                 if (!created)
2238                         return;
2239         }
2240         
2241         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2242
2243         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2244                 account_name = g_strdup (data->account_name);
2245         }
2246         
2247         /* Get the currently-active transport account for this modest account: */
2248         TnyTransportAccount *transport_account =
2249                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
2250                                       (modest_runtime_get_account_store(),
2251                                        account_name));
2252         if (!transport_account) {
2253                 /* Run account setup wizard */
2254                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2255                 if (!created)
2256                         return;
2257         }
2258         
2259         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2260
2261         /* Create the mail operation */
2262         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
2263         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2264
2265         modest_mail_operation_send_new_mail (mail_operation,
2266                                              transport_account,
2267                                              data->draft_msg,
2268                                              from,
2269                                              data->to, 
2270                                              data->cc, 
2271                                              data->bcc,
2272                                              data->subject, 
2273                                              data->plain_body, 
2274                                              data->html_body,
2275                                              data->attachments,
2276                                              data->images,
2277                                              data->priority_flags);
2278                                              
2279         /* Free data: */
2280         g_free (from);
2281         g_free (account_name);
2282         g_object_unref (G_OBJECT (transport_account));
2283         g_object_unref (G_OBJECT (mail_operation));
2284
2285         modest_msg_edit_window_free_msg_data (edit_window, data);
2286         modest_msg_edit_window_set_sent (edit_window, TRUE);
2287
2288         /* Save settings and close the window: */
2289         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2290 }
2291
2292 void 
2293 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2294                                   ModestMsgEditWindow *window)
2295 {
2296         ModestMsgEditFormatState *format_state = NULL;
2297
2298         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2299         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2300
2301         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2302                 return;
2303
2304         format_state = modest_msg_edit_window_get_format_state (window);
2305         g_return_if_fail (format_state != NULL);
2306
2307         format_state->bold = gtk_toggle_action_get_active (action);
2308         modest_msg_edit_window_set_format_state (window, format_state);
2309         g_free (format_state);
2310         
2311 }
2312
2313 void 
2314 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2315                                      ModestMsgEditWindow *window)
2316 {
2317         ModestMsgEditFormatState *format_state = NULL;
2318
2319         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2320         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2321
2322         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2323                 return;
2324
2325         format_state = modest_msg_edit_window_get_format_state (window);
2326         g_return_if_fail (format_state != NULL);
2327
2328         format_state->italics = gtk_toggle_action_get_active (action);
2329         modest_msg_edit_window_set_format_state (window, format_state);
2330         g_free (format_state);
2331         
2332 }
2333
2334 void 
2335 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2336                                      ModestMsgEditWindow *window)
2337 {
2338         ModestMsgEditFormatState *format_state = NULL;
2339
2340         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2341         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2342
2343         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2344                 return;
2345
2346         format_state = modest_msg_edit_window_get_format_state (window);
2347         g_return_if_fail (format_state != NULL);
2348
2349         format_state->bullet = gtk_toggle_action_get_active (action);
2350         modest_msg_edit_window_set_format_state (window, format_state);
2351         g_free (format_state);
2352         
2353 }
2354
2355 void 
2356 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2357                                      GtkRadioAction *selected,
2358                                      ModestMsgEditWindow *window)
2359 {
2360         ModestMsgEditFormatState *format_state = NULL;
2361         GtkJustification value;
2362
2363         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2364
2365         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2366                 return;
2367
2368         value = gtk_radio_action_get_current_value (selected);
2369
2370         format_state = modest_msg_edit_window_get_format_state (window);
2371         g_return_if_fail (format_state != NULL);
2372
2373         format_state->justification = value;
2374         modest_msg_edit_window_set_format_state (window, format_state);
2375         g_free (format_state);
2376 }
2377
2378 void 
2379 modest_ui_actions_on_select_editor_color (GtkAction *action,
2380                                           ModestMsgEditWindow *window)
2381 {
2382         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2383         g_return_if_fail (GTK_IS_ACTION (action));
2384
2385         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2386                 return;
2387
2388         modest_msg_edit_window_select_color (window);
2389 }
2390
2391 void 
2392 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2393                                                      ModestMsgEditWindow *window)
2394 {
2395         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2396         g_return_if_fail (GTK_IS_ACTION (action));
2397
2398         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2399                 return;
2400
2401         modest_msg_edit_window_select_background_color (window);
2402 }
2403
2404 void 
2405 modest_ui_actions_on_insert_image (GtkAction *action,
2406                                    ModestMsgEditWindow *window)
2407 {
2408         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2409         g_return_if_fail (GTK_IS_ACTION (action));
2410
2411         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2412                 return;
2413
2414         modest_msg_edit_window_insert_image (window);
2415 }
2416
2417 void 
2418 modest_ui_actions_on_attach_file (GtkAction *action,
2419                                   ModestMsgEditWindow *window)
2420 {
2421         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2422         g_return_if_fail (GTK_IS_ACTION (action));
2423
2424         modest_msg_edit_window_offer_attach_file (window);
2425 }
2426
2427 void 
2428 modest_ui_actions_on_remove_attachments (GtkAction *action,
2429                                          ModestMsgEditWindow *window)
2430 {
2431         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2432         g_return_if_fail (GTK_IS_ACTION (action));
2433
2434         modest_msg_edit_window_remove_attachments (window, NULL);
2435 }
2436
2437 static void
2438 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2439                                             gpointer user_data)
2440 {
2441         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2442         const GError *error = modest_mail_operation_get_error (mail_op);
2443
2444         if(error) {
2445                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2446                                                     _("mail_in_ui_folder_create_error"));
2447         }
2448 }
2449
2450 static void
2451 modest_ui_actions_create_folder(GtkWidget *parent_window,
2452                                 GtkWidget *folder_view)
2453 {
2454         TnyFolderStore *parent_folder;
2455
2456         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2457         
2458         if (parent_folder) {
2459                 gboolean finished = FALSE;
2460                 gint result;
2461                 gchar *folder_name = NULL, *suggested_name = NULL;
2462                 const gchar *proto_str = NULL;
2463                 TnyAccount *account;
2464
2465                 if (TNY_IS_ACCOUNT (parent_folder))
2466                         account = g_object_ref (parent_folder);
2467                 else
2468                         account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2469                 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2470
2471                 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2472                     MODEST_PROTOCOL_STORE_POP) {
2473                         finished = TRUE;
2474                         hildon_banner_show_information (NULL, NULL, _("mail_in_ui_folder_create_error"));
2475                 }
2476                 g_object_unref (account);
2477
2478                 /* Run the new folder dialog */
2479                 while (!finished) {
2480                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2481                                                                         parent_folder,
2482                                                                         suggested_name,
2483                                                                         &folder_name);
2484
2485                         g_free (suggested_name);
2486                         suggested_name = NULL;
2487
2488                         if (result == GTK_RESPONSE_REJECT) {
2489                                 finished = TRUE;
2490                         } else {
2491                                 ModestMailOperation *mail_op;
2492                                 TnyFolder *new_folder = NULL;
2493
2494                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2495                                                                                           G_OBJECT(parent_window),
2496                                                                                           modest_ui_actions_new_folder_error_handler,
2497                                                                                           parent_window);
2498
2499                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2500                                                                  mail_op);
2501                                 new_folder = modest_mail_operation_create_folder (mail_op,
2502                                                                                   parent_folder,
2503                                                                                   (const gchar *) folder_name);
2504                                 if (new_folder) {
2505                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2506                                                                           new_folder, TRUE);
2507
2508                                         g_object_unref (new_folder);
2509                                         finished = TRUE;
2510                                 }
2511                                 g_object_unref (mail_op);
2512                         }
2513
2514                         suggested_name = folder_name;
2515                         folder_name = NULL;
2516                 }
2517
2518                 g_object_unref (parent_folder);
2519         }
2520 }
2521
2522 void 
2523 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2524 {
2525         GtkWidget *folder_view;
2526         
2527         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2528
2529         folder_view = modest_main_window_get_child_widget (main_window,
2530                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2531         if (!folder_view)
2532                 return;
2533
2534         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2535 }
2536
2537 static void
2538 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2539                                                gpointer user_data)
2540 {
2541         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2542         const GError *error = NULL;
2543         const gchar *message = NULL;
2544         
2545         /* Get error message */
2546         error = modest_mail_operation_get_error (mail_op);
2547         if (!error)
2548                 g_return_if_reached ();
2549
2550         switch (error->code) {
2551         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2552                 message = _CS("ckdg_ib_folder_already_exists");
2553                 break;
2554         default:
2555                 g_return_if_reached ();
2556         }
2557
2558         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2559 }
2560
2561 void 
2562 modest_ui_actions_on_rename_folder (GtkAction *action,
2563                                      ModestMainWindow *main_window)
2564 {
2565         TnyFolderStore *folder;
2566         GtkWidget *folder_view;
2567         GtkWidget *header_view; 
2568
2569         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2570
2571         folder_view = modest_main_window_get_child_widget (main_window,
2572                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2573         if (!folder_view)
2574                 return;
2575
2576         header_view = modest_main_window_get_child_widget (main_window,
2577                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2578         
2579         if (!header_view)
2580                 return;
2581
2582         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2583
2584         if (!folder)
2585                 return;
2586
2587         if (TNY_IS_FOLDER (folder)) {
2588                 gchar *folder_name;
2589                 gint response;
2590                 const gchar *current_name;
2591                 TnyFolderStore *parent;
2592                 gboolean do_rename = TRUE;
2593
2594                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2595                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2596                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2597                                                                      parent, current_name, 
2598                                                                      &folder_name);
2599                 g_object_unref (parent);
2600
2601                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2602                         do_rename = FALSE;
2603                 } else if (modest_platform_is_network_folderstore(folder) &&
2604                            !tny_device_is_online (modest_runtime_get_device())) {
2605                         TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2606                         do_rename = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2607                         g_object_unref(account);
2608                 }
2609
2610                 if (do_rename) {
2611                         ModestMailOperation *mail_op;
2612                         GtkTreeSelection *sel = NULL;
2613
2614                         mail_op = 
2615                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2616                                                                                G_OBJECT(main_window),
2617                                                                                modest_ui_actions_rename_folder_error_handler,
2618                                                                                main_window);
2619
2620                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2621                                                          mail_op);
2622
2623                         /* Clear the headers view */
2624                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2625                         gtk_tree_selection_unselect_all (sel);
2626
2627                         /* Select *after* the changes */
2628                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2629                                                           TNY_FOLDER(folder), TRUE);
2630
2631                         /* Actually rename the folder */
2632                         modest_mail_operation_rename_folder (mail_op,
2633                                                              TNY_FOLDER (folder),
2634                                                              (const gchar *) folder_name);
2635
2636                         g_object_unref (mail_op);
2637                         g_free (folder_name);
2638                 }
2639         }
2640         g_object_unref (folder);
2641 }
2642
2643 static void
2644 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2645                                                gpointer user_data)
2646 {
2647         GObject *win = modest_mail_operation_get_source (mail_op);
2648
2649         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2650                                                 _("mail_in_ui_folder_delete_error"));
2651         g_object_unref (win);
2652 }
2653
2654 static gboolean
2655 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2656 {
2657         TnyFolderStore *folder;
2658         GtkWidget *folder_view;
2659         gint response;
2660         gchar *message;
2661         gboolean do_delete = TRUE;
2662
2663         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (main_window), FALSE);
2664
2665         folder_view = modest_main_window_get_child_widget (main_window,
2666                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2667         if (!folder_view)
2668                 return FALSE;
2669
2670         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2671
2672         /* Show an error if it's an account */
2673         if (!TNY_IS_FOLDER (folder)) {
2674                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2675                                                         _("mail_in_ui_folder_delete_error"));
2676                 g_object_unref (G_OBJECT (folder));
2677                 return FALSE;
2678         }
2679
2680         /* Ask the user */      
2681         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2682                                     tny_folder_get_name (TNY_FOLDER (folder)));
2683         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2684                                                             (const gchar *) message);
2685         g_free (message);
2686
2687         if (response != GTK_RESPONSE_OK) {
2688                 do_delete = FALSE;
2689         } else if (modest_platform_is_network_folderstore(folder) &&
2690                    !tny_device_is_online (modest_runtime_get_device())) {
2691                 TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2692                 do_delete = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2693                 g_object_unref(account);
2694         }
2695
2696         if (do_delete) {
2697                 ModestMailOperation *mail_op;
2698                 GtkTreeSelection *sel;
2699
2700                 /* Unselect the folder before deleting it to free the headers */
2701                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2702                 gtk_tree_selection_unselect_all (sel);
2703
2704                 /* Create the mail operation */
2705                 mail_op =
2706                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2707                                                                        G_OBJECT(main_window),
2708                                                                        modest_ui_actions_delete_folder_error_handler,
2709                                                                        NULL);
2710
2711                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2712                                                  mail_op);
2713                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2714                 g_object_unref (G_OBJECT (mail_op));
2715         }
2716
2717         g_object_unref (G_OBJECT (folder));
2718
2719         return do_delete;
2720 }
2721
2722 void 
2723 modest_ui_actions_on_delete_folder (GtkAction *action,
2724                                      ModestMainWindow *main_window)
2725 {
2726         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2727
2728         if (delete_folder (main_window, FALSE)) {
2729                 GtkWidget *folder_view;
2730
2731                 folder_view = modest_main_window_get_child_widget (main_window,
2732                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2733                 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2734         }
2735 }
2736
2737 void 
2738 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2739 {
2740         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2741         
2742         delete_folder (main_window, TRUE);
2743 }
2744
2745
2746 static void
2747 show_error (GtkWidget *parent_widget, const gchar* text)
2748 {
2749         hildon_banner_show_information(parent_widget, NULL, text);
2750         
2751 #if 0
2752         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2753         /*
2754           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2755           (GtkDialogFlags)0,
2756           GTK_MESSAGE_ERROR,
2757           GTK_BUTTONS_OK,
2758           text ));
2759         */
2760                  
2761         gtk_dialog_run (dialog);
2762         gtk_widget_destroy (GTK_WIDGET (dialog));
2763 #endif
2764 }
2765
2766 void
2767 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2768                                          const gchar* server_account_name,
2769                                          gchar **username,
2770                                          gchar **password, 
2771                                          gboolean *cancel, 
2772                                          gboolean *remember,
2773                                          ModestMainWindow *main_window)
2774 {
2775         g_return_if_fail(server_account_name);
2776         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2777         
2778         /* Initalize output parameters: */
2779         if (cancel)
2780                 *cancel = FALSE;
2781                 
2782         if (remember)
2783                 *remember = TRUE;
2784                 
2785 #ifdef MODEST_PLATFORM_MAEMO
2786         /* Maemo uses a different (awkward) button order,
2787          * It should probably just use gtk_alternative_dialog_button_order ().
2788          */
2789         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2790                                               NULL,
2791                                               GTK_DIALOG_MODAL,
2792                                               _("mcen_bd_dialog_ok"),
2793                                               GTK_RESPONSE_ACCEPT,
2794                                               _("mcen_bd_dialog_cancel"),
2795                                               GTK_RESPONSE_REJECT,
2796                                               NULL);
2797 #else
2798         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2799                                               NULL,
2800                                               GTK_DIALOG_MODAL,
2801                                               GTK_STOCK_CANCEL,
2802                                               GTK_RESPONSE_REJECT,
2803                                               GTK_STOCK_OK,
2804                                               GTK_RESPONSE_ACCEPT,
2805                                               NULL);
2806 #endif /* MODEST_PLATFORM_MAEMO */
2807
2808         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2809         
2810         gchar *server_name = modest_account_mgr_get_server_account_hostname (
2811                 modest_runtime_get_account_mgr(), server_account_name);
2812         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2813                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2814                 *cancel = TRUE;
2815                 return;
2816         }
2817         
2818         /* This causes a warning because the logical ID has no %s in it, 
2819          * though the translation does, but there is not much we can do about that: */
2820         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2821         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2822                             FALSE, FALSE, 0);
2823         g_free (txt);
2824         g_free (server_name);
2825         server_name = NULL;
2826
2827         /* username: */
2828         gchar *initial_username = modest_account_mgr_get_server_account_username (
2829                 modest_runtime_get_account_mgr(), server_account_name);
2830         
2831         GtkWidget *entry_username = gtk_entry_new ();
2832         if (initial_username)
2833                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2834         /* Dim this if a connection has ever succeeded with this username,
2835          * as per the UI spec: */
2836         const gboolean username_known = 
2837                 modest_account_mgr_get_server_account_username_has_succeeded(
2838                         modest_runtime_get_account_mgr(), server_account_name);
2839         gtk_widget_set_sensitive (entry_username, !username_known);
2840         
2841 #ifdef MODEST_PLATFORM_MAEMO
2842         /* Auto-capitalization is the default, so let's turn it off: */
2843         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2844         
2845         /* Create a size group to be used by all captions.
2846          * Note that HildonCaption does not create a default size group if we do not specify one.
2847          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2848         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2849         
2850         GtkWidget *caption = hildon_caption_new (sizegroup, 
2851                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2852         gtk_widget_show (entry_username);
2853         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2854                 FALSE, FALSE, MODEST_MARGIN_HALF);
2855         gtk_widget_show (caption);
2856 #else 
2857         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2858                             TRUE, FALSE, 0);
2859 #endif /* MODEST_PLATFORM_MAEMO */      
2860                             
2861         /* password: */
2862         GtkWidget *entry_password = gtk_entry_new ();
2863         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2864         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2865         
2866 #ifdef MODEST_PLATFORM_MAEMO
2867         /* Auto-capitalization is the default, so let's turn it off: */
2868         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2869                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2870         
2871         caption = hildon_caption_new (sizegroup, 
2872                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2873         gtk_widget_show (entry_password);
2874         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2875                 FALSE, FALSE, MODEST_MARGIN_HALF);
2876         gtk_widget_show (caption);
2877         g_object_unref (sizegroup);
2878 #else 
2879         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2880                             TRUE, FALSE, 0);
2881 #endif /* MODEST_PLATFORM_MAEMO */      
2882
2883         if (initial_username != NULL)
2884                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
2885                                 
2886 /* This is not in the Maemo UI spec:
2887         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2888         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2889                             TRUE, FALSE, 0);
2890 */
2891
2892         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2893         
2894         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2895                 if (username) {
2896                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2897                         
2898                         modest_account_mgr_set_server_account_username (
2899                                  modest_runtime_get_account_mgr(), server_account_name, 
2900                                  *username);
2901                                  
2902                         const gboolean username_was_changed = 
2903                                 (strcmp (*username, initial_username) != 0);
2904                         if (username_was_changed) {
2905                                 g_warning ("%s: tinymail does not yet support changing the "
2906                                         "username in the get_password() callback.\n", __FUNCTION__);
2907                         }
2908                 }
2909                         
2910                 if (password) {
2911                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2912                         
2913                         /* We do not save the password in the configuration, 
2914                          * because this function is only called for passwords that should 
2915                          * not be remembered:
2916                         modest_server_account_set_password (
2917                                  modest_runtime_get_account_mgr(), server_account_name, 
2918                                  *password);
2919                         */
2920                 }
2921                 
2922                 if (cancel)
2923                         *cancel   = FALSE;
2924                         
2925         } else {
2926                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2927                 
2928                 if (username)
2929                         *username = NULL;
2930                         
2931                 if (password)
2932                         *password = NULL;
2933                         
2934                 if (cancel)
2935                         *cancel   = TRUE;
2936         }
2937
2938 /* This is not in the Maemo UI spec:
2939         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2940                 *remember = TRUE;
2941         else
2942                 *remember = FALSE;
2943 */
2944
2945         gtk_widget_destroy (dialog);
2946         
2947         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2948 }
2949
2950 void
2951 modest_ui_actions_on_cut (GtkAction *action,
2952                           ModestWindow *window)
2953 {
2954         GtkWidget *focused_widget;
2955         GtkClipboard *clipboard;
2956
2957         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2958         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2959         if (GTK_IS_EDITABLE (focused_widget)) {
2960                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2961                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2962                 gtk_clipboard_store (clipboard);
2963         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2964                 GtkTextBuffer *buffer;
2965
2966                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2967                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2968                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2969                 gtk_clipboard_store (clipboard);
2970         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2971                 TnyList *header_list = modest_header_view_get_selected_headers (
2972                                 MODEST_HEADER_VIEW (focused_widget));
2973                 gboolean continue_download = FALSE;
2974                 gint num_of_unc_msgs;
2975
2976                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
2977
2978                 if (num_of_unc_msgs)
2979                         continue_download = connect_to_get_msg(
2980                                                                 GTK_WINDOW (window),
2981                                                                 num_of_unc_msgs);
2982
2983                 if (num_of_unc_msgs == 0 || continue_download) {
2984 /*                      modest_platform_information_banner (
2985                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
2986                         modest_header_view_cut_selection (
2987                                         MODEST_HEADER_VIEW (focused_widget));
2988                 }
2989
2990                 g_object_unref (header_list);
2991         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2992                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2993         }
2994 }
2995
2996 void
2997 modest_ui_actions_on_copy (GtkAction *action,
2998                            ModestWindow *window)
2999 {
3000         GtkClipboard *clipboard;
3001         GtkWidget *focused_widget;
3002         gboolean copied = TRUE;
3003
3004         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3005         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3006
3007         if (GTK_IS_LABEL (focused_widget)) {
3008                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
3009                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3010                 gtk_clipboard_store (clipboard);
3011         } else if (GTK_IS_EDITABLE (focused_widget)) {
3012                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3013                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3014                 gtk_clipboard_store (clipboard);
3015         } else if (GTK_IS_HTML (focused_widget)) {
3016                 gtk_html_copy (GTK_HTML (focused_widget));
3017                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3018                 gtk_clipboard_store (clipboard);
3019         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3020                 GtkTextBuffer *buffer;
3021                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3022                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3023                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3024                 gtk_clipboard_store (clipboard);
3025         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3026                 TnyList *header_list = modest_header_view_get_selected_headers (
3027                                 MODEST_HEADER_VIEW (focused_widget));
3028                 gboolean continue_download = FALSE;
3029                 gint num_of_unc_msgs;
3030
3031                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3032
3033                 if (num_of_unc_msgs)
3034                         continue_download = connect_to_get_msg(
3035                                                                 GTK_WINDOW (window),
3036                                                                 num_of_unc_msgs);
3037
3038                 if (num_of_unc_msgs == 0 || continue_download) {
3039                         modest_platform_information_banner (
3040                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3041                         modest_header_view_copy_selection (
3042                                         MODEST_HEADER_VIEW (focused_widget));
3043                 } else
3044                         copied = FALSE;
3045
3046                 g_object_unref (header_list);
3047
3048         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3049                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3050         }
3051
3052         /* Show information banner if there was a copy to clipboard */
3053         if(copied)
3054                 modest_platform_information_banner (
3055                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3056 }
3057
3058 void
3059 modest_ui_actions_on_undo (GtkAction *action,
3060                            ModestWindow *window)
3061 {
3062         ModestEmailClipboard *clipboard = NULL;
3063
3064         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3065                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3066         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3067                 /* Clear clipboard source */
3068                 clipboard = modest_runtime_get_email_clipboard ();
3069                 modest_email_clipboard_clear (clipboard);               
3070         }
3071         else {
3072                 g_return_if_reached ();
3073         }
3074 }
3075
3076 void
3077 modest_ui_actions_on_redo (GtkAction *action,
3078                            ModestWindow *window)
3079 {
3080         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3081                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3082         }
3083         else {
3084                 g_return_if_reached ();
3085         }
3086 }
3087
3088
3089 static void
3090 destroy_information_note (ModestMailOperation *mail_op, gpointer user_data)
3091 {
3092         /* destroy information note */
3093         gtk_widget_destroy (GTK_WIDGET(user_data));
3094 }
3095
3096
3097 static void
3098 paste_as_attachment_free (gpointer data)
3099 {
3100         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3101
3102         gtk_widget_destroy (helper->banner);
3103         g_object_unref (helper->banner);
3104         g_free (helper);
3105 }
3106
3107 static void
3108 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3109                             TnyHeader *header,
3110                             TnyMsg *msg,
3111                             gpointer userdata)
3112 {
3113         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3114         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3115
3116         if (msg == NULL)
3117                 return;
3118
3119         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3120         
3121 }
3122
3123 void
3124 modest_ui_actions_on_paste (GtkAction *action,
3125                             ModestWindow *window)
3126 {
3127         GtkWidget *focused_widget = NULL;
3128         GtkWidget *inf_note = NULL;
3129         ModestMailOperation *mail_op = NULL;
3130
3131         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3132         if (GTK_IS_EDITABLE (focused_widget)) {
3133                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3134         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3135                 ModestEmailClipboard *e_clipboard = NULL;
3136                 e_clipboard = modest_runtime_get_email_clipboard ();
3137                 if (modest_email_clipboard_cleared (e_clipboard)) {
3138                         GtkTextBuffer *buffer;
3139                         GtkClipboard *clipboard;
3140
3141                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3142                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3143                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3144                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3145                         ModestMailOperation *mail_op;
3146                         TnyFolder *src_folder;
3147                         TnyList *data;
3148                         gboolean delete;
3149                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3150                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3151                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3152                                                                            _CS("ckct_nw_pasting"));
3153                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3154                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3155                                                              G_OBJECT (window));
3156                         if (helper->banner != NULL) {
3157                                 g_object_ref (G_OBJECT (helper->banner));
3158                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3159                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3160                         }
3161
3162                         if (data != NULL) {
3163                                 modest_mail_operation_get_msgs_full (mail_op, 
3164                                                                      data,
3165                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3166                                                                      helper,
3167                                                                      paste_as_attachment_free);
3168                         }
3169                 }
3170         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3171                 ModestEmailClipboard *clipboard = NULL;
3172                 TnyFolder *src_folder = NULL;
3173                 TnyFolderStore *folder_store = NULL;
3174                 TnyList *data = NULL;           
3175                 gboolean delete = FALSE;
3176                 
3177                 /* Check clipboard source */
3178                 clipboard = modest_runtime_get_email_clipboard ();
3179                 if (modest_email_clipboard_cleared (clipboard)) 
3180                         return;
3181                 
3182                 /* Get elements to paste */
3183                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3184
3185                 /* Create a new mail operation */
3186                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
3187                 
3188                 /* Get destination folder */
3189                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3190
3191                 /* transfer messages  */
3192                 if (data != NULL) {
3193                         gint response = 0;
3194
3195                         /* Ask for user confirmation */
3196                         response = 
3197                                 modest_ui_actions_msgs_move_to_confirmation (GTK_WINDOW (window), 
3198                                                                              TNY_FOLDER (folder_store), 
3199                                                                              delete,
3200                                                                              data);
3201                         
3202                         if (response == GTK_RESPONSE_OK) {
3203                                 /* Launch notification */
3204                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3205                                                                              _CS("ckct_nw_pasting"));
3206                                 if (inf_note != NULL)  {
3207                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3208                                         gtk_widget_show (GTK_WIDGET(inf_note));
3209                                 }
3210
3211                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3212                                 modest_mail_operation_xfer_msgs (mail_op, 
3213                                                                  data,
3214                                                                  TNY_FOLDER (folder_store),
3215                                                                  delete,
3216                                                                  destroy_information_note,
3217                                                                  inf_note);                             
3218                         } else {
3219                                 g_object_unref (mail_op);
3220                         }
3221                         
3222                 } else if (src_folder != NULL) {                        
3223                         /* Launch notification */
3224                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3225                                                                      _CS("ckct_nw_pasting"));
3226                         if (inf_note != NULL)  {
3227                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3228                                 gtk_widget_show (GTK_WIDGET(inf_note));
3229                         }
3230                         
3231                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3232                         modest_mail_operation_xfer_folder (mail_op, 
3233                                                            src_folder,
3234                                                            folder_store,
3235                                                            delete,
3236                                                            destroy_information_note,
3237                                                            inf_note);
3238                 }
3239
3240                 /* Free */
3241                 if (data != NULL) 
3242                         g_object_unref (data);
3243                 if (src_folder != NULL) 
3244                         g_object_unref (src_folder);
3245                 if (folder_store != NULL) 
3246                         g_object_unref (folder_store);
3247         }
3248 }
3249
3250
3251 void
3252 modest_ui_actions_on_select_all (GtkAction *action,
3253                                  ModestWindow *window)
3254 {
3255         GtkWidget *focused_widget;
3256
3257         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3258         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3259                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3260         } else if (GTK_IS_LABEL (focused_widget)) {
3261                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3262         } else if (GTK_IS_EDITABLE (focused_widget)) {
3263                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3264         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3265                 GtkTextBuffer *buffer;
3266                 GtkTextIter start, end;
3267
3268                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3269                 gtk_text_buffer_get_start_iter (buffer, &start);
3270                 gtk_text_buffer_get_end_iter (buffer, &end);
3271                 gtk_text_buffer_select_range (buffer, &start, &end);
3272         } else if (GTK_IS_HTML (focused_widget)) {
3273                 gtk_html_select_all (GTK_HTML (focused_widget));
3274         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3275                 GtkWidget *header_view = focused_widget;
3276                 GtkTreeSelection *selection = NULL;
3277                 
3278                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3279                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3280                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3281                 }
3282                                 
3283                 /* Disable window dimming management */
3284                 modest_window_disable_dimming (MODEST_WINDOW(window));
3285                 
3286                 /* Select all messages */
3287                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3288                 gtk_tree_selection_select_all (selection);
3289
3290                 /* Set focuse on header view */
3291                 gtk_widget_grab_focus (header_view);
3292
3293
3294                 /* Enable window dimming management */
3295                 modest_window_enable_dimming (MODEST_WINDOW(window));
3296                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3297         }
3298
3299 }
3300
3301 void
3302 modest_ui_actions_on_mark_as_read (GtkAction *action,
3303                                    ModestWindow *window)
3304 {       
3305         g_return_if_fail (MODEST_IS_WINDOW(window));
3306                 
3307         /* Mark each header as read */
3308         do_headers_action (window, headers_action_mark_as_read, NULL);
3309 }
3310
3311 void
3312 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3313                                      ModestWindow *window)
3314 {       
3315         g_return_if_fail (MODEST_IS_WINDOW(window));
3316                 
3317         /* Mark each header as read */
3318         do_headers_action (window, headers_action_mark_as_unread, NULL);
3319 }
3320
3321 void
3322 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3323                                   GtkRadioAction *selected,
3324                                   ModestWindow *window)
3325 {
3326         gint value;
3327
3328         value = gtk_radio_action_get_current_value (selected);
3329         if (MODEST_IS_WINDOW (window)) {
3330                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3331         }
3332 }
3333
3334 void     
3335 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3336                                                GtkRadioAction *selected,
3337                                                ModestWindow *window)
3338 {
3339         TnyHeaderFlags flags;
3340         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3341
3342         flags = gtk_radio_action_get_current_value (selected);
3343         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3344 }
3345
3346 void     
3347 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3348                                                   GtkRadioAction *selected,
3349                                                   ModestWindow *window)
3350 {
3351         gint file_format;
3352
3353         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3354
3355         file_format = gtk_radio_action_get_current_value (selected);
3356         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3357 }
3358
3359
3360 void     
3361 modest_ui_actions_on_zoom_plus (GtkAction *action,
3362                                 ModestWindow *window)
3363 {
3364         g_return_if_fail (MODEST_IS_WINDOW (window));
3365
3366         modest_window_zoom_plus (MODEST_WINDOW (window));
3367 }
3368
3369 void     
3370 modest_ui_actions_on_zoom_minus (GtkAction *action,
3371                                  ModestWindow *window)
3372 {
3373         g_return_if_fail (MODEST_IS_WINDOW (window));
3374
3375         modest_window_zoom_minus (MODEST_WINDOW (window));
3376 }
3377
3378 void     
3379 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3380                                            ModestWindow *window)
3381 {
3382         ModestWindowMgr *mgr;
3383         gboolean fullscreen, active;
3384         g_return_if_fail (MODEST_IS_WINDOW (window));
3385
3386         mgr = modest_runtime_get_window_mgr ();
3387
3388         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3389         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3390
3391         if (active != fullscreen) {
3392                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3393                 gtk_window_present (GTK_WINDOW (window));
3394         }
3395 }
3396
3397 void
3398 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3399                                         ModestWindow *window)
3400 {
3401         ModestWindowMgr *mgr;
3402         gboolean fullscreen;
3403
3404         g_return_if_fail (MODEST_IS_WINDOW (window));
3405
3406         mgr = modest_runtime_get_window_mgr ();
3407         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3408         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3409
3410         gtk_window_present (GTK_WINDOW (window));
3411 }
3412
3413 /* 
3414  * Used by modest_ui_actions_on_details to call do_headers_action 
3415  */
3416 static void
3417 headers_action_show_details (TnyHeader *header, 
3418                              ModestWindow *window,
3419                              gpointer user_data)
3420
3421 {
3422         GtkWidget *dialog;
3423         
3424         /* Create dialog */
3425         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3426
3427         /* Run dialog */
3428         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3429         gtk_widget_show_all (dialog);
3430         gtk_dialog_run (GTK_DIALOG (dialog));
3431
3432         gtk_widget_destroy (dialog);
3433 }
3434
3435 /*
3436  * Show the folder details in a ModestDetailsDialog widget
3437  */
3438 static void
3439 show_folder_details (TnyFolder *folder, 
3440                      GtkWindow *window)
3441 {
3442         GtkWidget *dialog;
3443         
3444         /* Create dialog */
3445         dialog = modest_details_dialog_new_with_folder (window, folder);
3446
3447         /* Run dialog */
3448         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3449         gtk_widget_show_all (dialog);
3450         gtk_dialog_run (GTK_DIALOG (dialog));
3451
3452         gtk_widget_destroy (dialog);
3453 }
3454
3455 /*
3456  * Show the header details in a ModestDetailsDialog widget
3457  */
3458 void     
3459 modest_ui_actions_on_details (GtkAction *action, 
3460                               ModestWindow *win)
3461 {
3462         TnyList * headers_list;
3463         TnyIterator *iter;
3464         TnyHeader *header;              
3465
3466         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3467                 TnyMsg *msg;
3468
3469                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3470                 if (!msg)
3471                         return;
3472                 g_object_unref (msg);           
3473
3474                 headers_list = get_selected_headers (win);
3475                 if (!headers_list)
3476                         return;
3477
3478                 iter = tny_list_create_iterator (headers_list);
3479
3480                 header = TNY_HEADER (tny_iterator_get_current (iter));
3481                 if (header) {
3482                         headers_action_show_details (header, win, NULL);
3483                         g_object_unref (header);
3484                 }
3485
3486                 g_object_unref (iter);
3487                 g_object_unref (headers_list);
3488
3489         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3490                 GtkWidget *folder_view, *header_view;
3491
3492                 /* Check which widget has the focus */
3493                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3494                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3495                 if (gtk_widget_is_focus (folder_view)) {
3496                         TnyFolderStore *folder_store
3497                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3498                         if (!folder_store) {
3499                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3500                                 return; 
3501                         }
3502                         /* Show only when it's a folder */
3503                         /* This function should not be called for account items, 
3504                          * because we dim the menu item for them. */
3505                         if (TNY_IS_FOLDER (folder_store)) {
3506                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3507                         }
3508
3509                         g_object_unref (folder_store);
3510
3511                 } else {
3512                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3513                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3514                         /* Show details of each header */
3515                         do_headers_action (win, headers_action_show_details, header_view);
3516                 }
3517         }
3518 }
3519
3520 void     
3521 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3522                                      ModestMsgEditWindow *window)
3523 {
3524         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3525
3526         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3527 }
3528
3529 void     
3530 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3531                                       ModestMsgEditWindow *window)
3532 {
3533         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3534
3535         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3536 }
3537
3538 void
3539 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3540                                        ModestMainWindow *main_window)
3541 {
3542         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3543
3544         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3545                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3546         else
3547                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3548 }
3549
3550 void 
3551 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3552                                      ModestWindow *window)
3553 {
3554         gboolean active, fullscreen = FALSE;
3555         ModestWindowMgr *mgr;
3556
3557         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3558
3559         /* Check if we want to toggle the toolbar vuew in fullscreen
3560            or normal mode */
3561         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3562                      "ViewShowToolbarFullScreen")) {
3563                 fullscreen = TRUE;
3564         }
3565
3566         /* Toggle toolbar */
3567         mgr = modest_runtime_get_window_mgr ();
3568         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3569 }
3570
3571 void     
3572 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3573                                            ModestMsgEditWindow *window)
3574 {
3575         modest_msg_edit_window_select_font (window);
3576 }
3577
3578 void
3579 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3580                                                   const gchar *display_name,
3581                                                   GtkWindow *window)
3582 {
3583         /* Do not change the application name if the widget has not
3584            the focus. This callback could be called even if the folder
3585            view has not the focus, because the handled signal could be
3586            emitted when the folder view is redrawn */
3587         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3588                 if (display_name)
3589                         gtk_window_set_title (window, display_name);
3590                 else
3591                         gtk_window_set_title (window, " ");
3592         }
3593 }
3594
3595 void
3596 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3597 {
3598         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3599         modest_msg_edit_window_select_contacts (window);
3600 }
3601
3602 void
3603 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3604 {
3605         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3606         modest_msg_edit_window_check_names (window, FALSE);
3607 }
3608
3609 static void
3610 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3611 {
3612         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3613                                          GTK_WIDGET (user_data));
3614 }
3615
3616 /*
3617  * This function is used to track changes in the selection of the
3618  * folder view that is inside the "move to" dialog to enable/disable
3619  * the OK button because we do not want the user to select a disallowed
3620  * destination for a folder.
3621  * The user also not desired to be able to use NEW button on items where
3622  * folder creation is not possibel.
3623  */
3624 static void
3625 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3626                                             TnyFolderStore *folder_store,
3627                                             gboolean selected,
3628                                             gpointer user_data)
3629 {
3630         GtkWidget *dialog = NULL;
3631         GtkWidget *ok_button = NULL, *new_button = NULL;
3632         GList *children = NULL;
3633         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3634         gboolean moving_folder = FALSE;
3635         gboolean is_local_account = TRUE;
3636         GtkWidget *folder_view = NULL;
3637         ModestTnyFolderRules rules;
3638
3639         if (!selected)
3640                 return;
3641
3642         /* Get the OK button */
3643         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3644         if (!dialog)
3645                 return;
3646
3647         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3648         ok_button = GTK_WIDGET (children->next->next->data);
3649         new_button = GTK_WIDGET (children->next->data);
3650         g_list_free (children);
3651
3652         /* check if folder_store is an remote account */
3653         if (TNY_IS_ACCOUNT (folder_store)) {
3654                 TnyAccount *local_account = NULL;
3655                 ModestTnyAccountStore *account_store = NULL;
3656
3657                 account_store = modest_runtime_get_account_store ();
3658                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3659
3660                 if ((gpointer) local_account != (gpointer) folder_store) {
3661                         is_local_account = FALSE;
3662                         /* New button should be dimmed on remote
3663                            account root */
3664                         new_sensitive = FALSE;
3665                 }
3666                 g_object_unref (local_account);
3667         }
3668
3669         /* Check the target folder rules */
3670         if (TNY_IS_FOLDER (folder_store)) {
3671                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3672                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3673                         ok_sensitive = FALSE;
3674                         new_sensitive = FALSE;
3675                         goto end;
3676                 }
3677         }
3678
3679         /* Check if we're moving a folder */
3680         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3681                 /* Get the widgets */
3682                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3683                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3684                 if (gtk_widget_is_focus (folder_view))
3685                         moving_folder = TRUE;
3686         }
3687
3688         if (moving_folder) {
3689                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3690
3691                 /* Get the folder to move */
3692                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3693                 
3694                 /* Check that we're not moving to the same folder */
3695                 if (TNY_IS_FOLDER (moved_folder)) {
3696                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3697                         if (parent == folder_store)
3698                                 ok_sensitive = FALSE;
3699                         g_object_unref (parent);
3700                 } 
3701
3702                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3703                         /* Do not allow to move to an account unless it's the
3704                            local folders account */
3705                         if (!is_local_account)
3706                                 ok_sensitive = FALSE;
3707                 } 
3708
3709                 if (ok_sensitive && (moved_folder == folder_store)) {
3710                         /* Do not allow to move to itself */
3711                         ok_sensitive = FALSE;
3712                 }
3713                 g_object_unref (moved_folder);
3714         } else {
3715                 TnyHeader *header = NULL;
3716                 TnyFolder *src_folder = NULL;
3717
3718                 /* Moving a message */
3719                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3720                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3721                         src_folder = tny_header_get_folder (header);
3722                         g_object_unref (header);
3723                 } else {
3724                         src_folder = 
3725                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3726                 }
3727
3728                 /* Do not allow to move the msg to the same folder */
3729                 /* Do not allow to move the msg to an account */
3730                 if ((gpointer) src_folder == (gpointer) folder_store ||
3731                     TNY_IS_ACCOUNT (folder_store))
3732                         ok_sensitive = FALSE;
3733                 g_object_unref (src_folder);
3734         }
3735
3736  end:
3737         /* Set sensitivity of the OK button */
3738         gtk_widget_set_sensitive (ok_button, ok_sensitive);
3739         /* Set sensitivity of the NEW button */
3740         gtk_widget_set_sensitive (new_button, new_sensitive);
3741 }
3742
3743 static GtkWidget*
3744 create_move_to_dialog (GtkWindow *win,
3745                        GtkWidget *folder_view,
3746                        GtkWidget **tree_view)
3747 {
3748         GtkWidget *dialog, *scroll;
3749         GtkWidget *new_button;
3750
3751         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3752                                               GTK_WINDOW (win),
3753                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3754                                               NULL);
3755
3756         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3757         /* We do this manually so GTK+ does not associate a response ID for
3758          * the button. */
3759         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3760         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3761         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3762
3763         /* Create scrolled window */
3764         scroll = gtk_scrolled_window_new (NULL, NULL);
3765         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3766                                          GTK_POLICY_AUTOMATIC,
3767                                          GTK_POLICY_AUTOMATIC);
3768
3769         /* Create folder view */
3770         *tree_view = modest_platform_create_folder_view (NULL);
3771
3772         /* Track changes in the selection to
3773          * disable the OK button whenever "Move to" is not possible
3774          * disbale NEW button whenever New is not possible */
3775         g_signal_connect (*tree_view,
3776                           "folder_selection_changed",
3777                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3778                           win);
3779
3780         /* Listen to clicks on New button */
3781         g_signal_connect (G_OBJECT (new_button), 
3782                           "clicked", 
3783                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3784                           *tree_view);
3785
3786         /* It could happen that we're trying to move a message from a
3787            window (msg window for example) after the main window was
3788            closed, so we can not just get the model of the folder
3789            view */
3790         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3791                 const gchar *visible_id = NULL;
3792
3793                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3794                                                MODEST_FOLDER_VIEW(*tree_view));
3795
3796                 visible_id = 
3797                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3798
3799                 /* Show the same account than the one that is shown in the main window */
3800                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3801                                                                              visible_id);
3802         } else {
3803                 const gchar *active_account_name = NULL;
3804                 ModestAccountMgr *mgr = NULL;
3805                 ModestAccountData *acc_data = NULL;
3806
3807                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3808                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3809
3810                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3811                 mgr = modest_runtime_get_account_mgr ();
3812                 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3813
3814                 /* Set the new visible & active account */
3815                 if (acc_data && acc_data->store_account) { 
3816                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3817                                                                                      acc_data->store_account->account_name);
3818                         modest_account_mgr_free_account_data (mgr, acc_data);
3819                 }
3820         }
3821
3822         /* Hide special folders */
3823         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3824         
3825         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3826
3827         /* Add scroll to dialog */
3828         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3829                             scroll, TRUE, TRUE, 0);
3830
3831         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3832         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3833
3834         return dialog;
3835 }
3836
3837 /*
3838  * Returns TRUE if at least one of the headers of the list belongs to
3839  * a message that has been fully retrieved.
3840  */
3841 #if 0 /* no longer in use. delete in 2007.10 */
3842 static gboolean
3843 has_retrieved_msgs (TnyList *list)
3844 {
3845         TnyIterator *iter;
3846         gboolean found = FALSE;
3847
3848         iter = tny_list_create_iterator (list);
3849         while (!tny_iterator_is_done (iter) && !found) {
3850                 TnyHeader *header;
3851                 TnyHeaderFlags flags = 0;
3852
3853                 header = TNY_HEADER (tny_iterator_get_current (iter));
3854                 if (header) {
3855                         flags = tny_header_get_flags (header);
3856                         if (flags & TNY_HEADER_FLAG_CACHED)
3857 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3858                                 found = TRUE;
3859
3860                         g_object_unref (header);
3861                 }
3862
3863                 if (!found)
3864                         tny_iterator_next (iter);
3865         }
3866         g_object_unref (iter);
3867
3868         return found;
3869 }
3870 #endif /* 0 */
3871
3872
3873 /*
3874  * Shows a confirmation dialog to the user when we're moving messages
3875  * from a remote server to the local storage. Returns the dialog
3876  * response. If it's other kind of movement then it always returns
3877  * GTK_RESPONSE_OK
3878  *
3879  * This one is used by the next functions:
3880  *      modest_ui_actions_on_paste                      - commented out
3881  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
3882  */
3883 gint
3884 modest_ui_actions_msgs_move_to_confirmation (GtkWindow *win,
3885                                              TnyFolder *dest_folder,
3886                                              gboolean delete,
3887                                              TnyList *headers)
3888 {
3889         gint response = GTK_RESPONSE_OK;
3890
3891         /* return with OK if the destination is a remote folder */
3892         if (modest_tny_folder_is_remote_folder (dest_folder))
3893                 return GTK_RESPONSE_OK;
3894
3895         TnyFolder *src_folder = NULL;
3896         TnyIterator *iter = NULL;
3897         TnyHeader *header = NULL;
3898
3899         /* Get source folder */
3900         iter = tny_list_create_iterator (headers);
3901         header = TNY_HEADER (tny_iterator_get_current (iter));
3902         if (header) {
3903                 src_folder = tny_header_get_folder (header);
3904                 g_object_unref (header);
3905         }
3906         g_object_unref (iter);
3907
3908         /* if no src_folder, message may be an attahcment */
3909         if (src_folder == NULL) 
3910                 return GTK_RESPONSE_CANCEL;
3911
3912         /* If the source is a local or MMC folder */
3913         if (!modest_tny_folder_is_remote_folder (src_folder)) {
3914                 g_object_unref (src_folder);
3915                 return GTK_RESPONSE_OK;
3916         }
3917         g_object_unref (src_folder);
3918
3919         /* now if offline we ask the user */
3920         if(connect_to_get_msg(  GTK_WINDOW (win),
3921                                         tny_list_get_length (headers)))
3922                 response = GTK_RESPONSE_OK;
3923         else
3924                 response = GTK_RESPONSE_CANCEL;
3925
3926         return response;
3927 }
3928
3929
3930
3931 static void
3932 move_to_cb (ModestMailOperation *mail_op, gpointer user_data)
3933 {
3934         MoveToHelper *helper = (MoveToHelper *) user_data;
3935
3936         /* Note that the operation could have failed, in that case do
3937            nothing */
3938         if (modest_mail_operation_get_status (mail_op) == 
3939             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
3940
3941                 GObject *object = modest_mail_operation_get_source (mail_op);
3942                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
3943                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
3944
3945                         if (!modest_msg_view_window_select_next_message (self))
3946                                 if (!modest_msg_view_window_select_previous_message (self))
3947                                         /* No more messages to view, so close this window */
3948                                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3949                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
3950                         GtkWidget *header_view;
3951                         GtkTreePath *path;
3952                         GtkTreeSelection *sel;
3953
3954                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
3955                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3956                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
3957                         path = gtk_tree_row_reference_get_path (helper->reference);
3958                         gtk_tree_selection_select_path (sel, path);
3959                         gtk_tree_path_free (path);
3960                 }
3961                 g_object_unref (object);
3962         }
3963
3964         /* Close the "Pasting" information banner */
3965         gtk_widget_destroy (GTK_WIDGET(helper->banner));
3966         if (helper->reference != NULL)
3967                 gtk_tree_row_reference_free (helper->reference);
3968         g_free (helper);
3969 }
3970
3971 void
3972 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3973                                              gpointer user_data)
3974 {
3975         ModestWindow *main_window = NULL;
3976         GtkWidget *folder_view = NULL;
3977         GObject *win = modest_mail_operation_get_source (mail_op);
3978         const GError *error = NULL;
3979         const gchar *message = NULL;
3980         
3981         /* Get error message */
3982         error = modest_mail_operation_get_error (mail_op);
3983         if (error != NULL && error->message != NULL) {
3984                 message = error->message;
3985         } else {
3986                 message = _("mail_in_ui_folder_move_target_error");
3987         }
3988         
3989         /* Disable next automatic folder selection */
3990         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ());
3991         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
3992                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
3993         modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
3994         
3995         if (user_data && TNY_IS_FOLDER (user_data)) {
3996                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
3997                                                   TNY_FOLDER (user_data), FALSE);
3998         }
3999
4000         /* Show notification dialog */
4001         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
4002         g_object_unref (win);
4003 }
4004
4005 void
4006 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
4007                                               gpointer user_data)
4008 {
4009         GObject *win = modest_mail_operation_get_source (mail_op);
4010         const GError *error = modest_mail_operation_get_error (mail_op);
4011
4012         g_return_if_fail (error != NULL);
4013         if (error->message != NULL)             
4014                 g_printerr ("modest: %s\n", error->message);
4015         else
4016                 g_printerr ("modest: unkonw error on send&receive operation");
4017
4018         /* Show error message */
4019 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
4020 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4021 /*                                                      _CS("sfil_ib_unable_to_receive")); */
4022 /*      else  */
4023 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4024 /*                                                      _CS("sfil_ib_unable_to_send")); */
4025         g_object_unref (win);
4026 }
4027
4028 static void
4029 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4030                        TnyHeader *header, 
4031                        TnyMsg *msg, 
4032                        gpointer user_data)
4033 {
4034         TnyList *parts;
4035         TnyIterator *iter;
4036         gint pending_purges = 0;
4037         gboolean some_purged = FALSE;
4038         ModestWindow *win = MODEST_WINDOW (user_data);
4039         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4040
4041         /* If there was any error */
4042         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4043                 modest_window_mgr_unregister_header (mgr, header);
4044                 return;
4045         }
4046
4047         /* Once the message has been retrieved for purging, we check if
4048          * it's all ok for purging */
4049
4050         parts = tny_simple_list_new ();
4051         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4052         iter = tny_list_create_iterator (parts);
4053
4054         while (!tny_iterator_is_done (iter)) {
4055                 TnyMimePart *part;
4056                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4057                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4058                         if (tny_mime_part_is_purged (part))
4059                                 some_purged = TRUE;
4060                         else
4061                                 pending_purges++;
4062                 }
4063
4064                 if (part)
4065                         g_object_unref (part);
4066
4067                 tny_iterator_next (iter);
4068         }
4069         g_object_unref (iter);
4070         
4071
4072         if (pending_purges>0) {
4073                 gint response;
4074                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4075
4076                 if (response == GTK_RESPONSE_OK) {
4077                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4078                         iter = tny_list_create_iterator (parts);
4079                         while (!tny_iterator_is_done (iter)) {
4080                                 TnyMimePart *part;
4081                                 
4082                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4083                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4084                                         tny_mime_part_set_purged (part);
4085
4086                                 if (part)
4087                                         g_object_unref (part);
4088
4089                                 tny_iterator_next (iter);
4090                         }
4091                         
4092                         tny_msg_rewrite_cache (msg);
4093                 }
4094         } else {
4095                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
4096         }
4097         g_object_unref (iter);
4098
4099         modest_window_mgr_unregister_header (mgr, header);
4100
4101         g_object_unref (parts);
4102 }
4103
4104 static void
4105 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4106                                                      ModestMainWindow *win)
4107 {
4108         GtkWidget *header_view;
4109         TnyList *header_list;
4110         TnyIterator *iter;
4111         TnyHeader *header;
4112         TnyHeaderFlags flags;
4113         ModestWindow *msg_view_window =  NULL;
4114         gboolean found;
4115
4116         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4117
4118         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4119                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4120
4121         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4122
4123         if (tny_list_get_length (header_list) == 1) {
4124                 iter = tny_list_create_iterator (header_list);
4125                 header = TNY_HEADER (tny_iterator_get_current (iter));
4126                 g_object_unref (iter);
4127         } else {
4128                 return;
4129         }
4130
4131         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4132                                                           header, &msg_view_window);
4133         flags = tny_header_get_flags (header);
4134         if (!(flags & TNY_HEADER_FLAG_CACHED))
4135                 return;
4136         if (found) {
4137                 if (msg_view_window != NULL) 
4138                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4139                 else {
4140                         /* do nothing; uid was registered before, so window is probably on it's way */
4141                         g_warning ("debug: header %p has already been registered", header);
4142                 }
4143         } else {
4144                 ModestMailOperation *mail_op = NULL;
4145                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
4146                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4147                                                                          G_OBJECT (win),
4148                                                                          modest_ui_actions_get_msgs_full_error_handler,
4149                                                                          NULL);
4150                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4151                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4152                 
4153                 g_object_unref (mail_op);
4154         }
4155         if (header)
4156                 g_object_unref (header);
4157         if (header_list)
4158                 g_object_unref (header_list);
4159 }
4160
4161 /**
4162  * Utility function that transfer messages from both the main window
4163  * and the msg view window when using the "Move to" dialog
4164  */
4165 static void
4166 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
4167                                               ModestWindow *win)
4168 {
4169         TnyList *headers = NULL;
4170         TnyAccount *dst_account = NULL;
4171         const gchar *proto_str = NULL;
4172         gboolean dst_is_pop = FALSE;
4173
4174         if (!TNY_IS_FOLDER (dst_folder)) {
4175                 modest_platform_information_banner (GTK_WIDGET (win),
4176                                                     NULL,
4177                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
4178                 return;
4179         }
4180
4181         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4182         proto_str = tny_account_get_proto (dst_account);
4183
4184         /* tinymail will return NULL for local folders it seems */
4185         dst_is_pop = proto_str &&
4186                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4187                  MODEST_PROTOCOL_STORE_POP);
4188
4189         g_object_unref (dst_account);
4190
4191         /* Get selected headers */
4192         headers = get_selected_headers (MODEST_WINDOW (win));
4193
4194         if (dst_is_pop) {
4195                 modest_platform_information_banner (GTK_WIDGET (win),
4196                                                     NULL,
4197                                                     ngettext("mail_in_ui_folder_move_target_error",
4198                                                              "mail_in_ui_folder_move_targets_error",
4199                                                              tny_list_get_length (headers)));
4200                 g_object_unref (headers);
4201                 return;
4202         }
4203
4204         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4205         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4206                                                            _CS("ckct_nw_pasting"));
4207         if (helper->banner != NULL)  {
4208                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4209                 gtk_widget_show (GTK_WIDGET(helper->banner));
4210         }
4211
4212         if (MODEST_IS_MAIN_WINDOW (win)) {
4213                 GtkWidget *header_view = 
4214                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4215                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4216                 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4217         }
4218
4219         ModestMailOperation *mail_op = 
4220                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4221                                                                G_OBJECT(win),
4222                                                                modest_ui_actions_move_folder_error_handler,
4223                                                                NULL);
4224         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4225                                          mail_op);
4226
4227         modest_mail_operation_xfer_msgs (mail_op, 
4228                                          headers,
4229                                          TNY_FOLDER (dst_folder),
4230                                          TRUE,
4231                                          move_to_cb,
4232                                          helper);
4233
4234         g_object_unref (G_OBJECT (mail_op));
4235         g_object_unref (headers);
4236 }
4237
4238 /*
4239  * UI handler for the "Move to" action when invoked from the
4240  * ModestMainWindow
4241  */
4242 static void 
4243 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4244                                           GtkWidget *folder_view,
4245                                           TnyFolderStore *dst_folder,
4246                                           ModestMainWindow *win)
4247 {
4248         ModestHeaderView *header_view = NULL;
4249         ModestMailOperation *mail_op = NULL;
4250         TnyFolderStore *src_folder;
4251         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4252
4253         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4254
4255         /* Get the source folder */
4256         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4257
4258         /* Get header view */
4259         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4260
4261         /* Get folder or messages to transfer */
4262         if (gtk_widget_is_focus (folder_view)) {
4263                 GtkTreeSelection *sel;
4264                 gboolean do_xfer = TRUE;
4265
4266                 /* Allow only to transfer folders to the local root folder */
4267                 if (TNY_IS_ACCOUNT (dst_folder) && 
4268                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4269                         do_xfer = FALSE;
4270                 } else if (!TNY_IS_FOLDER (src_folder)) {
4271                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4272                         do_xfer = FALSE;
4273                 } else if (!online && modest_platform_is_network_folderstore(src_folder)) {
4274                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER(src_folder));
4275                         if (!connect_to_get_msg(GTK_WINDOW(win), num_headers)) {
4276                                 do_xfer = FALSE;
4277                         }
4278                 }
4279
4280                 if (do_xfer) {
4281                         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4282                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4283                                                                            _CS("ckct_nw_pasting"));
4284                         if (helper->banner != NULL)  {
4285                                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4286                                 gtk_widget_show (GTK_WIDGET(helper->banner));
4287                         }
4288                         /* Clean folder on header view before moving it */
4289                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4290                         gtk_tree_selection_unselect_all (sel);
4291
4292                         mail_op =
4293                           modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4294                                                                          G_OBJECT(win),
4295                                                                          modest_ui_actions_move_folder_error_handler,
4296                                                                          src_folder);
4297                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4298                                                          mail_op);
4299
4300                         /* Select *after* the changes */
4301                         /* TODO: this function hangs UI after transfer */ 
4302 /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4303 /*                                                        TNY_FOLDER (src_folder), TRUE); */
4304                         
4305                         modest_mail_operation_xfer_folder (mail_op,
4306                                                            TNY_FOLDER (src_folder),
4307                                                            dst_folder,
4308                                                            TRUE, 
4309                                                            move_to_cb, 
4310                                                            helper);
4311                         /* Unref mail operation */
4312                         g_object_unref (G_OBJECT (mail_op));
4313                 }
4314         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4315                 gboolean do_xfer = TRUE;
4316                 /* Ask for confirmation if the source folder is remote and we're not connected */
4317                 if (!online && modest_platform_is_network_folderstore(src_folder)) {
4318                         TnyList *headers = modest_header_view_get_selected_headers(header_view);
4319                         if (!msgs_already_deleted_from_server(headers, src_folder)) {
4320                                 guint num_headers = tny_list_get_length(headers);
4321                                 if (!connect_to_get_msg(GTK_WINDOW(win), num_headers)) {
4322                                         do_xfer = FALSE;
4323                                 }
4324                         }
4325                         g_object_unref(headers);
4326                 }
4327                 if (do_xfer) /* Transfer messages */
4328                         modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4329         }
4330
4331     if (src_folder)
4332         g_object_unref (src_folder);
4333 }
4334
4335
4336 /*
4337  * UI handler for the "Move to" action when invoked from the
4338  * ModestMsgViewWindow
4339  */
4340 static void 
4341 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4342                                               TnyFolderStore *dst_folder,
4343                                               ModestMsgViewWindow *win)
4344 {
4345         TnyHeader *header = NULL;
4346         TnyFolderStore *src_folder;
4347
4348         /* Create header list */
4349         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4350         src_folder = TNY_FOLDER_STORE(tny_header_get_folder(header));
4351         g_object_unref (header);
4352
4353         /* Transfer the message if online or confirmed by the user */
4354         if (tny_device_is_online (modest_runtime_get_device()) || remote_folder_is_pop(src_folder) ||
4355             (modest_platform_is_network_folderstore(src_folder) && connect_to_get_msg(GTK_WINDOW(win), 1))) {
4356                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4357         }
4358
4359         g_object_unref (src_folder);
4360 }
4361
4362 void 
4363 modest_ui_actions_on_move_to (GtkAction *action, 
4364                               ModestWindow *win)
4365 {
4366         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4367         gint result = 0;
4368         TnyFolderStore *dst_folder = NULL;
4369         ModestMainWindow *main_window;
4370
4371         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4372                           MODEST_IS_MSG_VIEW_WINDOW (win));
4373
4374         /* Get the main window if exists */
4375         if (MODEST_IS_MAIN_WINDOW (win))
4376                 main_window = MODEST_MAIN_WINDOW (win);
4377         else
4378                 main_window = 
4379                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
4380
4381         /* Get the folder view widget if exists */
4382         if (main_window)
4383                 folder_view = modest_main_window_get_child_widget (main_window,
4384                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4385         else
4386                 folder_view = NULL;
4387
4388         /* Create and run the dialog */
4389         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4390         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4391         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4392         result = gtk_dialog_run (GTK_DIALOG(dialog));
4393         g_object_ref (tree_view);
4394         gtk_widget_destroy (dialog);
4395
4396         if (result != GTK_RESPONSE_ACCEPT)
4397                 return;
4398
4399         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4400         /* Do window specific stuff */
4401         if (MODEST_IS_MAIN_WINDOW (win)) {
4402                 modest_ui_actions_on_main_window_move_to (action,
4403                                                           folder_view,
4404                                                           dst_folder,
4405                                                           MODEST_MAIN_WINDOW (win));
4406         } else {
4407                 modest_ui_actions_on_msg_view_window_move_to (action,
4408                                                               dst_folder,
4409                                                               MODEST_MSG_VIEW_WINDOW (win));
4410         }
4411
4412         if (dst_folder)
4413                 g_object_unref (dst_folder);
4414 }
4415
4416 /*
4417  * Calls #HeadersFunc for each header already selected in the main
4418  * window or the message currently being shown in the msg view window
4419  */
4420 static void
4421 do_headers_action (ModestWindow *win, 
4422                    HeadersFunc func,
4423                    gpointer user_data)
4424 {
4425         TnyList *headers_list = NULL;
4426         TnyIterator *iter = NULL;
4427         TnyHeader *header = NULL;
4428         TnyFolder *folder = NULL;
4429
4430         /* Get headers */
4431         headers_list = get_selected_headers (win);
4432         if (!headers_list)
4433                 return;
4434
4435         /* Get the folder */
4436         iter = tny_list_create_iterator (headers_list);
4437         header = TNY_HEADER (tny_iterator_get_current (iter));
4438         if (header) {
4439                 folder = tny_header_get_folder (header);
4440                 g_object_unref (header);
4441         }
4442
4443         /* Call the function for each header */
4444         while (!tny_iterator_is_done (iter)) {
4445                 header = TNY_HEADER (tny_iterator_get_current (iter));
4446                 func (header, win, user_data);
4447                 g_object_unref (header);
4448                 tny_iterator_next (iter);
4449         }
4450
4451         /* Trick: do a poke status in order to speed up the signaling
4452            of observers */
4453         tny_folder_poke_status (folder);
4454
4455         /* Frees */
4456         g_object_unref (folder);
4457         g_object_unref (iter);
4458         g_object_unref (headers_list);
4459 }
4460
4461 void 
4462 modest_ui_actions_view_attachment (GtkAction *action,
4463                                    ModestWindow *window)
4464 {
4465         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4466                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4467         } else {
4468                 /* not supported window for this action */
4469                 g_return_if_reached ();
4470         }
4471 }
4472
4473 void
4474 modest_ui_actions_save_attachments (GtkAction *action,
4475                                     ModestWindow *window)
4476 {
4477         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4478                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4479         } else {
4480                 /* not supported window for this action */
4481                 g_return_if_reached ();
4482         }
4483 }
4484
4485 void
4486 modest_ui_actions_remove_attachments (GtkAction *action,
4487                                       ModestWindow *window)
4488 {
4489         if (MODEST_IS_MAIN_WINDOW (window)) {
4490                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4491         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4492                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4493         } else {
4494                 /* not supported window for this action */
4495                 g_return_if_reached ();
4496         }
4497 }
4498
4499 void 
4500 modest_ui_actions_on_settings (GtkAction *action, 
4501                                ModestWindow *win)
4502 {
4503         GtkWidget *dialog;
4504
4505         dialog = modest_platform_get_global_settings_dialog ();
4506         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4507         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4508         gtk_widget_show_all (dialog);
4509
4510         gtk_dialog_run (GTK_DIALOG (dialog));
4511
4512         gtk_widget_destroy (dialog);
4513 }
4514
4515 void 
4516 modest_ui_actions_on_help (GtkAction *action, 
4517                            ModestWindow *win)
4518 {
4519         const gchar *help_id = NULL;
4520
4521         if (MODEST_IS_MAIN_WINDOW (win)) {
4522                 GtkWidget *folder_view;
4523                 TnyFolderStore *folder_store;
4524                 
4525                 /* Get selected folder */
4526                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4527                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4528                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4529
4530                 /* Switch help_id */
4531                 if (TNY_IS_FOLDER (folder_store)) {
4532                         switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
4533                         case TNY_FOLDER_TYPE_NORMAL:
4534                                 help_id = "applications_email_managefolders";
4535                                 break;
4536                         case TNY_FOLDER_TYPE_INBOX:
4537                                 help_id = "applications_email_inbox";
4538                                 break;
4539                         case TNY_FOLDER_TYPE_OUTBOX:
4540                                 help_id = "applications_email_outbox";
4541                                 break;
4542                         case TNY_FOLDER_TYPE_SENT:
4543                                 help_id = "applications_email_sent";
4544                                 break;
4545                         case TNY_FOLDER_TYPE_DRAFTS:
4546                                 help_id = "applications_email_drafts";
4547                                 break;
4548                         case TNY_FOLDER_TYPE_ARCHIVE:
4549                                 help_id = "applications_email_managefolders";
4550                                 break;
4551                         default:
4552                                 help_id = "applications_email_managefolders";
4553                         }
4554                 } else {
4555                         help_id = "applications_email_mainview";
4556                 }
4557                 g_object_unref (folder_store);
4558         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4559                 help_id = "applications_email_viewer";
4560         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
4561                 help_id = "applications_email_editor";
4562
4563         modest_platform_show_help (GTK_WINDOW (win), help_id);
4564 }
4565
4566 void 
4567 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4568                                             ModestWindow *window)
4569 {
4570         ModestMailOperation *mail_op;
4571         TnyList *headers;
4572
4573         /* Get headers */
4574         headers = get_selected_headers (window);
4575         if (!headers)
4576                 return;
4577
4578         /* Create mail operation */
4579         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4580                                                                  G_OBJECT (window),
4581                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4582                                                                  NULL);
4583         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4584         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4585
4586         /* Frees */
4587         g_object_unref (headers);
4588         g_object_unref (mail_op);
4589 }
4590
4591 void
4592 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4593                                           ModestWindow *window)
4594 {
4595         g_return_if_fail (MODEST_IS_WINDOW (window));
4596         
4597         /* Update dimmed */     
4598         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4599 }
4600
4601 void
4602 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4603                                           ModestWindow *window)
4604 {
4605         g_return_if_fail (MODEST_IS_WINDOW (window));
4606
4607         /* Update dimmed */     
4608         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4609 }
4610
4611 void
4612 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4613                                           ModestWindow *window)
4614 {
4615         g_return_if_fail (MODEST_IS_WINDOW (window));
4616
4617         /* Update dimmed */     
4618         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4619 }
4620
4621 void
4622 modest_ui_actions_on_format_menu_activated (GtkAction *action,
4623                                             ModestWindow *window)
4624 {
4625         g_return_if_fail (MODEST_IS_WINDOW (window));
4626
4627         /* Update dimmed */     
4628         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4629 }
4630
4631 void
4632 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4633                                           ModestWindow *window)
4634 {
4635         g_return_if_fail (MODEST_IS_WINDOW (window));
4636
4637         /* Update dimmed */     
4638         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4639 }
4640
4641 void
4642 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4643                                           ModestWindow *window)
4644 {
4645         g_return_if_fail (MODEST_IS_WINDOW (window));
4646
4647         /* Update dimmed */     
4648         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4649 }
4650
4651 void
4652 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4653                                                  ModestWindow *window)
4654 {
4655         g_return_if_fail (MODEST_IS_WINDOW (window));
4656
4657         /* Update dimmed */     
4658         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4659 }
4660
4661 void
4662 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4663                                                      ModestWindow *window)
4664 {
4665         g_return_if_fail (MODEST_IS_WINDOW (window));
4666
4667         /* Update dimmed */     
4668         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4669 }
4670
4671 void
4672 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4673                                                      ModestWindow *window)
4674 {
4675         g_return_if_fail (MODEST_IS_WINDOW (window));
4676
4677         /* Update dimmed */     
4678         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4679 }
4680
4681 void
4682 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4683 {
4684         g_return_if_fail (MODEST_IS_WINDOW (window));
4685
4686         /* Update dimmed */     
4687         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4688 }
4689
4690 void
4691 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4692 {
4693         g_return_if_fail (MODEST_IS_WINDOW (window));
4694
4695         modest_platform_show_search_messages (GTK_WINDOW (window));
4696 }
4697
4698 void     
4699 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4700 {
4701         g_return_if_fail (MODEST_IS_WINDOW (win));
4702         modest_platform_show_addressbook (GTK_WINDOW (win));
4703 }
4704
4705
4706 void
4707 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4708                                           ModestWindow *window)
4709 {
4710         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4711
4712         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4713 }
4714
4715 static void 
4716 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
4717                                    ModestMailOperationState *state,
4718                                    gpointer user_data)
4719 {
4720         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
4721
4722         /* Set send/receive operation finished */       
4723         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
4724                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
4725         
4726 }
4727
4728
4729 void 
4730 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
4731                                                 TnyHeader *header, 
4732                                                 TnyMsg *msg, 
4733                                                 GError *err, 
4734                                                 gpointer user_data)
4735 {
4736         const gchar* server_name = NULL;
4737         TnyTransportAccount *server_account;
4738         gchar *message = NULL;
4739
4740         /* Don't show anything if the user cancelled something */
4741         if (err->code == TNY_TRANSPORT_ACCOUNT_ERROR_SEND_USER_CANCEL)
4742                 return;
4743
4744         /* Get the server name: */
4745         server_account = 
4746                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
4747         if (server_account) {
4748                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
4749                         
4750                 g_object_unref (server_account);
4751                 server_account = NULL;
4752         }
4753         
4754         g_return_if_fail (server_name);
4755
4756         /* Show the appropriate message text for the GError: */
4757         switch (err->code) {
4758         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
4759                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4760                 break;
4761         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
4762                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4763                 break;
4764         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
4765                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
4766                 break;
4767         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
4768                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
4769                 break;
4770         default:
4771                 g_return_if_reached ();
4772         }
4773         
4774         /* TODO if the username or the password where not defined we
4775            should show the Accounts Settings dialog or the Connection
4776            specific SMTP server window */
4777
4778         modest_platform_run_information_dialog (NULL, message);
4779         g_free (message);
4780 }
4781
4782 void
4783 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
4784                                                 gchar *msg_id, 
4785                                                 guint status,
4786                                                 gpointer user_data)
4787 {
4788         ModestMainWindow *main_window = NULL;
4789         ModestWindowMgr *mgr = NULL;
4790         GtkWidget *folder_view = NULL, *header_view = NULL;
4791         TnyFolderStore *selected_folder = NULL;
4792         TnyFolderType folder_type;
4793
4794         mgr = modest_runtime_get_window_mgr ();
4795         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr));
4796
4797         if (!main_window)
4798                 return;
4799
4800         /* Check if selected folder is OUTBOX */
4801         folder_view = modest_main_window_get_child_widget (main_window,
4802                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4803         header_view = modest_main_window_get_child_widget (main_window,
4804                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4805
4806         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4807         if (!TNY_IS_FOLDER (selected_folder)) 
4808                 goto frees;
4809
4810         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
4811 #if GTK_CHECK_VERSION(2, 8, 0) 
4812         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
4813         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
4814                 GtkTreeViewColumn *tree_column;
4815
4816                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
4817                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
4818                 gtk_tree_view_column_queue_resize (tree_column);
4819         }
4820 #else
4821         gtk_widget_queue_draw (header_view);
4822 #endif          
4823         
4824         /* Free */
4825  frees:
4826         if (selected_folder != NULL)
4827                 g_object_unref (selected_folder);
4828 }