Work to fix NB#66729: after moving selected messages to another folder,
[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
1205         /* If there was any error. The mail operation could be NULL,
1206            this means that we already have the message downloaded and
1207            that we didn't do a mail operation to retrieve it */
1208         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1209                 return;
1210                         
1211         g_return_if_fail (user_data != NULL);
1212         rf_helper = (ReplyForwardHelper *) user_data;
1213
1214         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1215                                                    rf_helper->account_name);
1216         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
1217                                          rf_helper->account_name,
1218                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
1219                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
1220                                                            rf_helper->account_name,
1221                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
1222         }
1223
1224         /* Create reply mail */
1225         switch (rf_helper->action) {
1226         case ACTION_REPLY:
1227                 new_msg = 
1228                         modest_tny_msg_create_reply_msg (msg, header, from, signature,
1229                                                          rf_helper->reply_forward_type,
1230                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1231                 break;
1232         case ACTION_REPLY_TO_ALL:
1233                 new_msg = 
1234                         modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1235                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1236                 edit_type = MODEST_EDIT_TYPE_REPLY;
1237                 break;
1238         case ACTION_FORWARD:
1239                 new_msg = 
1240                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1241                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1242                 break;
1243         default:
1244                 g_return_if_reached ();
1245                 return;
1246         }
1247
1248         g_free (signature);
1249
1250         if (!new_msg) {
1251                 g_printerr ("modest: failed to create message\n");
1252                 goto cleanup;
1253         }
1254
1255         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1256                                                                        rf_helper->account_name,
1257                                                                        TNY_ACCOUNT_TYPE_STORE);
1258         if (!account) {
1259                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1260                 goto cleanup;
1261         }
1262
1263         /* Create and register the windows */
1264         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1265         mgr = modest_runtime_get_window_mgr ();
1266         modest_window_mgr_register_window (mgr, msg_win);
1267
1268         if (rf_helper->parent_window != NULL) {
1269                 gdouble parent_zoom;
1270
1271                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1272                 modest_window_set_zoom (msg_win, parent_zoom);
1273         }
1274
1275         /* Show edit window */
1276         gtk_widget_show_all (GTK_WIDGET (msg_win));
1277
1278 cleanup:
1279         if (msg_win)
1280                 g_object_unref (msg_win);
1281         if (new_msg)
1282                 g_object_unref (G_OBJECT (new_msg));
1283         if (account)
1284                 g_object_unref (G_OBJECT (account));
1285 /*      g_object_unref (msg); */
1286         free_reply_forward_helper (rf_helper);
1287 }
1288
1289 /* Checks a list of headers. If any of them are not currently
1290  * downloaded (CACHED) then returns TRUE else returns FALSE.
1291  */
1292 static gint
1293 header_list_count_uncached_msgs (TnyList *header_list)
1294 {
1295         TnyIterator *iter;
1296         gint uncached_messages = 0;
1297
1298         iter = tny_list_create_iterator (header_list);
1299         while (!tny_iterator_is_done (iter)) {
1300                 TnyHeader *header;
1301
1302                 header = TNY_HEADER (tny_iterator_get_current (iter));
1303                 if (header) {
1304                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1305                                 uncached_messages ++;
1306                         g_object_unref (header);
1307                 }
1308
1309                 tny_iterator_next (iter);
1310         }
1311         g_object_unref (iter);
1312
1313         return uncached_messages;
1314 }
1315
1316 /* Returns FALSE if the user does not want to download the
1317  * messages. Returns TRUE if the user allowed the download.
1318  */
1319 static gboolean
1320 connect_to_get_msg (GtkWindow *win,
1321                     gint num_of_uncached_msgs)
1322 {
1323         /* Allways download if we are online. */
1324         if (tny_device_is_online (modest_runtime_get_device ()))
1325                 return TRUE;
1326
1327         /* If offline, then ask for user permission to download the messages */
1328         GtkResponseType response;
1329         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1330                         ngettext("mcen_nc_get_msg",
1331                         "mcen_nc_get_msgs",
1332                         num_of_uncached_msgs));
1333         if (response == GTK_RESPONSE_CANCEL)
1334                 return FALSE;
1335
1336         return modest_platform_connect_and_wait(win, NULL);     
1337 }
1338
1339 /*
1340  * Common code for the reply and forward actions
1341  */
1342 static void
1343 reply_forward (ReplyForwardAction action, ModestWindow *win)
1344 {
1345         ModestMailOperation *mail_op = NULL;
1346         TnyList *header_list = NULL;
1347         ReplyForwardHelper *rf_helper = NULL;
1348         guint reply_forward_type;
1349         gboolean continue_download = TRUE;
1350         gboolean do_retrieve = TRUE;
1351         
1352         g_return_if_fail (MODEST_IS_WINDOW(win));
1353
1354         /* we need an account when editing */
1355         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1356                 const gboolean created = modest_run_account_setup_wizard (win);
1357                 if (!created)
1358                         return;
1359         }
1360         
1361         header_list = get_selected_headers (win);
1362         if (!header_list)
1363                 return;
1364
1365         reply_forward_type = 
1366                 modest_conf_get_int (modest_runtime_get_conf (),
1367                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1368                                      NULL);
1369
1370         /* check if we need to download msg before asking about it */
1371         do_retrieve = (action == ACTION_FORWARD) ||
1372                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1373
1374         if (do_retrieve){
1375                 gint num_of_unc_msgs;
1376                 /* check that the messages have been previously downloaded */
1377                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1378                 /* If there are any uncached message ask the user
1379                  * whether he/she wants to download them. */
1380                 if (num_of_unc_msgs)
1381                         continue_download = connect_to_get_msg (
1382                                                                 GTK_WINDOW (win),
1383                                                                 num_of_unc_msgs);
1384         }
1385
1386         if (!continue_download) {
1387                 g_object_unref (header_list);
1388                 return;
1389         }
1390         
1391         /* We assume that we can only select messages of the
1392            same folder and that we reply all of them from the
1393            same account. In fact the interface currently only
1394            allows single selection */
1395         
1396         /* Fill helpers */
1397         rf_helper = g_slice_new0 (ReplyForwardHelper);
1398         rf_helper->reply_forward_type = reply_forward_type;
1399         rf_helper->action = action;
1400         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1401         
1402         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1403                 rf_helper->parent_window = GTK_WIDGET (win);
1404         if (!rf_helper->account_name)
1405                 rf_helper->account_name =
1406                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1407
1408         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1409                 TnyMsg *msg;
1410                 TnyHeader *header;
1411                 /* Get header and message. Do not free them here, the
1412                    reply_forward_cb must do it */
1413                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1414                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1415                 if (!msg || !header) {
1416                         if (msg)
1417                                 g_object_unref (msg);
1418                         g_printerr ("modest: no message found\n");
1419                         return;
1420                 } else {
1421                         reply_forward_cb (NULL, header, msg, rf_helper);
1422                 }
1423                 if (header)
1424                         g_object_unref (header);
1425         } else {
1426                 TnyHeader *header;
1427                 TnyIterator *iter;
1428
1429                 /* Only reply/forward to one message */
1430                 iter = tny_list_create_iterator (header_list);
1431                 header = TNY_HEADER (tny_iterator_get_current (iter));
1432                 g_object_unref (iter);
1433
1434                 if (header) {
1435                         /* Retrieve messages */
1436                         if (do_retrieve) {
1437                                 mail_op = modest_mail_operation_new_with_error_handling (
1438                                         MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1439                                         G_OBJECT(win),
1440                                         modest_ui_actions_get_msgs_full_error_handler, 
1441                                         NULL);
1442                                 modest_mail_operation_queue_add (
1443                                         modest_runtime_get_mail_operation_queue (), mail_op);
1444                                 
1445                                 modest_mail_operation_get_msg (mail_op,
1446                                                                header,
1447                                                                reply_forward_cb,
1448                                                                rf_helper);
1449                                 /* Clean */
1450                                 g_object_unref(mail_op);
1451                         } else {
1452                                 /* we put a ref here to prevent double unref as the reply
1453                                  * forward callback unrefs the header at its end */
1454                                 reply_forward_cb (NULL, header, NULL, rf_helper);
1455                         }
1456
1457
1458                         g_object_unref (header);
1459                 }
1460
1461         }
1462
1463         /* Free */
1464         g_object_unref (header_list);
1465 }
1466
1467 void
1468 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1469 {
1470         g_return_if_fail (MODEST_IS_WINDOW(win));
1471
1472         reply_forward (ACTION_REPLY, win);
1473 }
1474
1475 void
1476 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1477 {
1478         g_return_if_fail (MODEST_IS_WINDOW(win));
1479
1480         reply_forward (ACTION_FORWARD, win);
1481 }
1482
1483 void
1484 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1485 {
1486         g_return_if_fail (MODEST_IS_WINDOW(win));
1487
1488         reply_forward (ACTION_REPLY_TO_ALL, win);
1489 }
1490
1491 void 
1492 modest_ui_actions_on_next (GtkAction *action, 
1493                            ModestWindow *window)
1494 {
1495         if (MODEST_IS_MAIN_WINDOW (window)) {
1496                 GtkWidget *header_view;
1497
1498                 header_view = modest_main_window_get_child_widget (
1499                                 MODEST_MAIN_WINDOW(window),
1500                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1501                 if (!header_view)
1502                         return;
1503         
1504                 modest_header_view_select_next (
1505                                 MODEST_HEADER_VIEW(header_view)); 
1506         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1507                 modest_msg_view_window_select_next_message (
1508                                 MODEST_MSG_VIEW_WINDOW (window));
1509         } else {
1510                 g_return_if_reached ();
1511         }
1512 }
1513
1514 void 
1515 modest_ui_actions_on_prev (GtkAction *action, 
1516                            ModestWindow *window)
1517 {
1518         g_return_if_fail (MODEST_IS_WINDOW(window));
1519
1520         if (MODEST_IS_MAIN_WINDOW (window)) {
1521                 GtkWidget *header_view;
1522                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1523                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1524                 if (!header_view)
1525                         return;
1526                 
1527                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1528         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1529                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1530         } else {
1531                 g_return_if_reached ();
1532         }
1533 }
1534
1535 void 
1536 modest_ui_actions_on_sort (GtkAction *action, 
1537                            ModestWindow *window)
1538 {
1539         g_return_if_fail (MODEST_IS_WINDOW(window));
1540
1541         if (MODEST_IS_MAIN_WINDOW (window)) {
1542                 GtkWidget *header_view;
1543                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1544                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1545                 if (!header_view) {
1546                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1547
1548                         return;
1549                 }
1550
1551                 /* Show sorting dialog */
1552                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1553         }
1554 }
1555
1556 static void
1557 new_messages_arrived (ModestMailOperation *self, 
1558                       TnyList *new_headers,
1559                       gpointer user_data)
1560 {
1561         ModestMainWindow *win = NULL;
1562         GtkWidget *folder_view = NULL;
1563         TnyFolderStore *folder = NULL;
1564         gboolean folder_empty = FALSE;
1565
1566         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
1567         win = MODEST_MAIN_WINDOW (user_data);
1568
1569         /* Don't do anything if there are not new headers, this could
1570            happen if there was any problem with the mail operation */
1571         if (!new_headers)
1572                 return;
1573
1574         /* Set contents style of headers view */
1575         if (modest_main_window_get_contents_style (win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1576                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1577                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1578                 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));             
1579                 
1580
1581                 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1582                 
1583                 if (!folder_empty)
1584                         modest_main_window_set_contents_style (win,
1585                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1586         }       
1587
1588         /* Notify new messages have been downloaded */
1589         if ((new_headers != NULL) && (tny_list_get_length (new_headers) > 0)) {
1590                 TnyIterator *iter = tny_list_create_iterator (new_headers);
1591                 do {
1592                         TnyHeader *header =  NULL;
1593
1594                         header = TNY_HEADER (tny_iterator_get_current (iter));
1595                         modest_platform_on_new_header_received (header);
1596                         g_object_unref (header);
1597
1598                         tny_iterator_next (iter);
1599                 } while (!tny_iterator_is_done (iter));
1600                 g_object_unref (iter);
1601         }
1602 }
1603
1604 /*
1605  * This function performs the send & receive required actions. The
1606  * window is used to create the mail operation. Typically it should
1607  * always be the main window, but we pass it as argument in order to
1608  * be more flexible.
1609  */
1610 void
1611 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1612 {
1613         gchar *acc_name = NULL;
1614         ModestMailOperation *mail_op;
1615         TnyAccount *store_account = NULL;
1616
1617         /* If no account name was provided then get the current account, and if
1618            there is no current account then pick the default one: */
1619         if (!account_name) {
1620                 acc_name = g_strdup (modest_window_get_active_account(win));
1621                 if (!acc_name)
1622                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1623                 if (!acc_name) {
1624                         g_printerr ("modest: cannot get default account\n");
1625                         return;
1626                 }
1627         } else {
1628                 acc_name = g_strdup (account_name);
1629         }
1630
1631
1632         /* Ensure that we have a connection available */
1633         store_account =
1634                 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1635                                                              acc_name,
1636                                                              TNY_ACCOUNT_TYPE_STORE);
1637         if (!modest_platform_connect_and_wait (NULL, TNY_ACCOUNT (store_account))) {
1638                 g_object_unref (store_account);
1639                 return;
1640         }
1641         g_object_unref (store_account);
1642
1643         /* Set send/receive operation in progress */    
1644         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1645
1646         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1647                                                                  G_OBJECT (win),
1648                                                                  modest_ui_actions_send_receive_error_handler,
1649                                                                  NULL);
1650
1651         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1652                           G_CALLBACK (_on_send_receive_progress_changed), 
1653                           win);
1654
1655         /* Send & receive. */
1656         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1657         /* Receive and then send. The operation is tagged initially as
1658            a receive operation because the account update performs a
1659            receive and then a send. The operation changes its type
1660            internally, so the progress objects will receive the proper
1661            progress information */
1662         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1663         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, win);
1664         g_object_unref (G_OBJECT (mail_op));
1665         
1666         /* Free */
1667         g_free (acc_name);
1668 }
1669
1670
1671 static void
1672 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1673                                   ModestWindow *win)
1674 {
1675         TnyTransportAccount *transport_account;
1676         TnySendQueue *send_queue = NULL;
1677         GError *error = NULL;
1678
1679         /* Get transport account */
1680         transport_account =
1681                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1682                                       (modest_runtime_get_account_store(),
1683                                        account_name,
1684                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1685         if (!transport_account) {
1686                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1687                 goto frees;
1688         }
1689
1690         /* Get send queue*/
1691         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1692         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1693                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1694                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1695                              "modest: could not find send queue for account\n");
1696         } else {
1697                 /* Keeep messages in outbox folder */
1698                 tny_send_queue_cancel (send_queue, FALSE, &error);
1699         }       
1700
1701  frees:
1702         if (transport_account != NULL) 
1703                 g_object_unref (G_OBJECT (transport_account));
1704 }
1705
1706 static void
1707 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1708 {
1709         GSList *account_names, *iter;
1710
1711         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1712                                                           TRUE);
1713
1714         iter = account_names;
1715         while (iter) {                  
1716                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1717                 iter = g_slist_next (iter);
1718         }
1719
1720         modest_account_mgr_free_account_names (account_names);
1721         account_names = NULL;
1722 }
1723
1724 void
1725 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1726
1727 {
1728         /* Check if accounts exist */
1729         gboolean accounts_exist = 
1730                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1731         
1732         /* If not, allow the user to create an account before trying to send/receive. */
1733         if (!accounts_exist)
1734                 modest_ui_actions_on_accounts (NULL, win);
1735         
1736         /* Cancel all sending operaitons */     
1737         modest_ui_actions_cancel_send_all (win);
1738 }
1739
1740 /*
1741  * Refreshes all accounts. This function will be used by automatic
1742  * updates
1743  */
1744 void
1745 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1746 {
1747         GSList *account_names, *iter;
1748
1749         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1750                                                           TRUE);
1751
1752         iter = account_names;
1753         while (iter) {                  
1754                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1755                 iter = g_slist_next (iter);
1756         }
1757
1758         modest_account_mgr_free_account_names (account_names);
1759         account_names = NULL;
1760 }
1761
1762 void 
1763 modest_do_refresh_current_folder(ModestWindow *win)
1764 {
1765         /* Refresh currently selected folder. Note that if we only
1766            want to retreive the headers, then the refresh only will
1767            invoke a poke_status over all folders, i.e., only the
1768            total/unread count will be updated */
1769         if (MODEST_IS_MAIN_WINDOW (win)) {
1770                 GtkWidget *header_view, *folder_view;
1771                 TnyFolderStore *folder_store;
1772
1773                 /* Get folder and header view */
1774                 folder_view = 
1775                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1776                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1777                 if (!folder_view)
1778                         return;
1779
1780                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1781
1782                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1783                         header_view = 
1784                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1785                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1786                 
1787                         /* We do not need to set the contents style
1788                            because it hasn't changed. We also do not
1789                            need to save the widget status. Just force
1790                            a refresh */
1791                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1792                                                        TNY_FOLDER (folder_store),
1793                                                        folder_refreshed_cb,
1794                                                        MODEST_MAIN_WINDOW (win));
1795                 }
1796                 
1797                 if (folder_store)
1798                         g_object_unref (folder_store);
1799         }
1800 }
1801
1802
1803 /*
1804  * Handler of the click on Send&Receive button in the main toolbar
1805  */
1806 void
1807 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1808 {
1809         /* Check if accounts exist */
1810         gboolean accounts_exist = 
1811                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1812         
1813         /* If not, allow the user to create an account before trying to send/receive. */
1814         if (!accounts_exist)
1815                 modest_ui_actions_on_accounts (NULL, win);
1816
1817         modest_do_refresh_current_folder (win);
1818         
1819         /* Refresh the active account */
1820         modest_ui_actions_do_send_receive (NULL, win);
1821 }
1822
1823
1824 void
1825 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1826 {
1827         ModestConf *conf;
1828         GtkWidget *header_view;
1829         
1830         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1831
1832         header_view = modest_main_window_get_child_widget (main_window,
1833                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1834         if (!header_view)
1835                 return;
1836
1837         conf = modest_runtime_get_conf ();
1838         
1839         /* what is saved/restored is depending on the style; thus; we save with
1840          * old style, then update the style, and restore for this new style
1841          */
1842         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1843         
1844         if (modest_header_view_get_style
1845             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1846                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1847                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1848         else
1849                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1850                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1851
1852         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1853                                       MODEST_CONF_HEADER_VIEW_KEY);
1854 }
1855
1856
1857 void 
1858 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1859                                       TnyHeader *header,
1860                                       ModestMainWindow *main_window)
1861 {
1862         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1863         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1864         
1865         /* in the case the folder is empty, show the empty folder message and focus
1866          * folder view */
1867         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1868                 if (modest_header_view_is_empty (header_view)) {
1869                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1870                         GtkWidget *folder_view = 
1871                                 modest_main_window_get_child_widget (main_window,
1872                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1873                         if (folder != NULL) 
1874                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1875                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1876                         return;
1877                 }
1878         }
1879         /* If no header has been selected then exit */
1880         if (!header)
1881                 return;
1882
1883         /* Update focus */
1884         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1885             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1886
1887         /* Update toolbar dimming state */
1888         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1889 }
1890
1891 void
1892 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1893                                        TnyHeader *header,
1894                                        ModestMainWindow *main_window)
1895 {
1896         TnyList *headers;
1897
1898         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1899         
1900         if (!header)
1901                 return;
1902
1903         if (modest_header_view_count_selected_headers (header_view) > 1) {
1904                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1905                 return;
1906         }
1907
1908
1909 /*      headers = tny_simple_list_new (); */
1910 /*      tny_list_prepend (headers, G_OBJECT (header)); */
1911         headers = modest_header_view_get_selected_headers (header_view);
1912
1913         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1914
1915         g_object_unref (headers);
1916 }
1917
1918 static void
1919 set_active_account_from_tny_account (TnyAccount *account,
1920                                      ModestWindow *window)
1921 {
1922         const gchar *server_acc_name = tny_account_get_id (account);
1923         
1924         /* We need the TnyAccount provided by the
1925            account store because that is the one that
1926            knows the name of the Modest account */
1927         TnyAccount *modest_server_account = modest_server_account = 
1928                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1929                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1930                                                              server_acc_name);
1931         if (!modest_server_account) {
1932                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
1933                 return;
1934         }
1935
1936         /* Update active account, but only if it's not a pseudo-account */
1937         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
1938             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
1939                 const gchar *modest_acc_name = 
1940                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1941                 if (modest_acc_name)
1942                         modest_window_set_active_account (window, modest_acc_name);
1943         }
1944         
1945         g_object_unref (modest_server_account);
1946 }
1947
1948
1949 static void
1950 folder_refreshed_cb (ModestMailOperation *mail_op, 
1951                      TnyFolder *folder, 
1952                      gpointer user_data)
1953 {
1954         ModestMainWindow *win = NULL;
1955         GtkWidget *header_view;
1956         gboolean folder_empty = FALSE;
1957         gboolean all_marked_as_deleted = FALSE;
1958
1959         g_return_if_fail (TNY_IS_FOLDER (folder));
1960
1961         win = MODEST_MAIN_WINDOW (user_data);
1962         header_view = 
1963                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1964
1965         if (header_view) {
1966                 TnyFolder *current_folder;
1967
1968                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
1969                 if (current_folder != NULL && folder != current_folder) {
1970                         g_object_unref (current_folder);
1971                         return;
1972                 }
1973                 g_object_unref (current_folder);
1974         }
1975
1976         /* Check if folder is empty and set headers view contents style */
1977         folder_empty = (tny_folder_get_all_count (folder) == 0);
1978         all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
1979         if (folder_empty || all_marked_as_deleted)
1980                 modest_main_window_set_contents_style (win,
1981                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1982 }
1983
1984 void 
1985 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1986                                                TnyFolderStore *folder_store, 
1987                                                gboolean selected,
1988                                                ModestMainWindow *main_window)
1989 {
1990         ModestConf *conf;
1991         GtkWidget *header_view;
1992
1993         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1994
1995         header_view = modest_main_window_get_child_widget(main_window,
1996                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1997         if (!header_view)
1998                 return;
1999         
2000         conf = modest_runtime_get_conf ();
2001
2002         if (TNY_IS_ACCOUNT (folder_store)) {
2003                 if (selected) {
2004                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2005                         
2006                         /* Show account details */
2007                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2008                 }
2009         } else {
2010                 if (TNY_IS_FOLDER (folder_store) && selected) {
2011                         
2012                         /* Update the active account */
2013                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2014                         if (account) {
2015                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2016                                 g_object_unref (account);
2017                                 account = NULL;
2018                         }
2019
2020                         /* Set the header style by default, it could
2021                            be changed later by the refresh callback to
2022                            empty */
2023                         modest_main_window_set_contents_style (main_window, 
2024                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2025
2026                         /* Set folder on header view. This function
2027                            will call tny_folder_refresh_async so we
2028                            pass a callback that will be called when
2029                            finished. We use that callback to set the
2030                            empty view if there are no messages */
2031                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2032                                                        TNY_FOLDER (folder_store),
2033                                                        folder_refreshed_cb,
2034                                                        main_window);
2035                         
2036                         /* Restore configuration. We need to do this
2037                            *after* the set_folder because the widget
2038                            memory asks the header view about its
2039                            folder  */
2040                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2041                                                       G_OBJECT(header_view),
2042                                                       MODEST_CONF_HEADER_VIEW_KEY);
2043                 } else {
2044                         /* Update the active account */
2045                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2046                         /* Save only if we're seeing headers */
2047                         if (modest_main_window_get_contents_style (main_window) ==
2048                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2049                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2050                                                            MODEST_CONF_HEADER_VIEW_KEY);
2051                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2052                 }
2053         }
2054
2055         /* Update toolbar dimming state */
2056         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2057 }
2058
2059 void 
2060 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2061                                      ModestWindow *win)
2062 {
2063         GtkWidget *dialog;
2064         gchar *txt, *item;
2065         gboolean online;
2066
2067         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2068         
2069         online = tny_device_is_online (modest_runtime_get_device());
2070
2071         if (online) {
2072                 /* already online -- the item is simply not there... */
2073                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2074                                                  GTK_DIALOG_MODAL,
2075                                                  GTK_MESSAGE_WARNING,
2076                                                  GTK_BUTTONS_NONE,
2077                                                  _("The %s you selected cannot be found"),
2078                                                  item);
2079                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2080                 gtk_dialog_run (GTK_DIALOG(dialog));
2081         } else {
2082                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2083                                                       GTK_WINDOW (win),
2084                                                       GTK_DIALOG_MODAL,
2085                                                       _("mcen_bd_dialog_cancel"),
2086                                                       GTK_RESPONSE_REJECT,
2087                                                       _("mcen_bd_dialog_ok"),
2088                                                       GTK_RESPONSE_ACCEPT,
2089                                                       NULL);
2090                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2091                                          "Do you want to get online?"), item);
2092                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2093                                     gtk_label_new (txt), FALSE, FALSE, 0);
2094                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2095                 g_free (txt);
2096
2097                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2098                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2099                         /* TODO: Comment about why is this commented out: */
2100                         /* modest_platform_connect_and_wait (); */
2101                 }
2102         }
2103         gtk_widget_destroy (dialog);
2104 }
2105
2106 void
2107 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2108                                      ModestWindow *win)
2109 {
2110         /* g_message ("%s %s", __FUNCTION__, link); */
2111 }       
2112
2113
2114 void
2115 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2116                                         ModestWindow *win)
2117 {
2118         modest_platform_activate_uri (link);
2119 }
2120
2121 void
2122 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2123                                           ModestWindow *win)
2124 {
2125         modest_platform_show_uri_popup (link);
2126 }
2127
2128 void
2129 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2130                                              ModestWindow *win)
2131 {
2132         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2133 }
2134
2135 void
2136 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2137                                           const gchar *address,
2138                                           ModestWindow *win)
2139 {
2140         /* g_message ("%s %s", __FUNCTION__, address); */
2141 }
2142
2143 void
2144 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2145 {
2146         TnyTransportAccount *transport_account;
2147         ModestMailOperation *mail_operation;
2148         MsgData *data;
2149         gchar *account_name, *from;
2150         ModestAccountMgr *account_mgr;
2151         gchar *info_text = NULL;
2152
2153         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2154         
2155         data = modest_msg_edit_window_get_msg_data (edit_window);
2156
2157         account_mgr = modest_runtime_get_account_mgr();
2158         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2159         if (!account_name) 
2160                 account_name = modest_account_mgr_get_default_account (account_mgr);
2161         if (!account_name) {
2162                 g_printerr ("modest: no account found\n");
2163                 modest_msg_edit_window_free_msg_data (edit_window, data);
2164                 return;
2165         }
2166
2167         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2168                 account_name = g_strdup (data->account_name);
2169         }
2170
2171         transport_account =
2172                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2173                                       (modest_runtime_get_account_store(),
2174                                        account_name,
2175                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2176         if (!transport_account) {
2177                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2178                 g_free (account_name);
2179                 modest_msg_edit_window_free_msg_data (edit_window, data);
2180                 return;
2181         }
2182         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2183
2184         /* Create the mail operation */         
2185         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
2186         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2187
2188         modest_mail_operation_save_to_drafts (mail_operation,
2189                                               transport_account,
2190                                               data->draft_msg,
2191                                               edit_window,
2192                                               from,
2193                                               data->to, 
2194                                               data->cc, 
2195                                               data->bcc,
2196                                               data->subject, 
2197                                               data->plain_body, 
2198                                               data->html_body,
2199                                               data->attachments,
2200                                               data->priority_flags);
2201         /* Frees */
2202         g_free (from);
2203         g_free (account_name);
2204         g_object_unref (G_OBJECT (transport_account));
2205         g_object_unref (G_OBJECT (mail_operation));
2206
2207         modest_msg_edit_window_free_msg_data (edit_window, data);
2208
2209         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2210         modest_platform_information_banner (NULL, NULL, info_text);
2211         modest_msg_edit_window_reset_modified (edit_window);
2212         g_free (info_text);
2213 }
2214
2215 /* For instance, when clicking the Send toolbar button when editing a message: */
2216 void
2217 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2218 {
2219         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2220
2221         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2222                 return;
2223         
2224         /* Offer the connection dialog, if necessary: */        
2225         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window), NULL))
2226                 return;
2227         
2228         /* FIXME: Code added just for testing. The final version will
2229            use the send queue provided by tinymail and some
2230            classifier */
2231         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2232         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2233         if (!account_name) 
2234                 account_name = modest_account_mgr_get_default_account (account_mgr);
2235                 
2236         if (!account_name) {
2237                 /* Run account setup wizard */
2238                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2239                 if (!created)
2240                         return;
2241         }
2242         
2243         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2244
2245         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2246                 account_name = g_strdup (data->account_name);
2247         }
2248         
2249         /* Get the currently-active transport account for this modest account: */
2250         TnyTransportAccount *transport_account =
2251                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
2252                                       (modest_runtime_get_account_store(),
2253                                        account_name));
2254         if (!transport_account) {
2255                 /* Run account setup wizard */
2256                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2257                 if (!created)
2258                         return;
2259         }
2260         
2261         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2262
2263         /* Create the mail operation */
2264         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
2265         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2266
2267         modest_mail_operation_send_new_mail (mail_operation,
2268                                              transport_account,
2269                                              data->draft_msg,
2270                                              from,
2271                                              data->to, 
2272                                              data->cc, 
2273                                              data->bcc,
2274                                              data->subject, 
2275                                              data->plain_body, 
2276                                              data->html_body,
2277                                              data->attachments,
2278                                              data->priority_flags);
2279                                              
2280         /* Free data: */
2281         g_free (from);
2282         g_free (account_name);
2283         g_object_unref (G_OBJECT (transport_account));
2284         g_object_unref (G_OBJECT (mail_operation));
2285
2286         modest_msg_edit_window_free_msg_data (edit_window, data);
2287         modest_msg_edit_window_set_sent (edit_window, TRUE);
2288
2289         /* Save settings and close the window: */
2290         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2291 }
2292
2293 void 
2294 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2295                                   ModestMsgEditWindow *window)
2296 {
2297         ModestMsgEditFormatState *format_state = NULL;
2298
2299         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2300         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2301
2302         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2303                 return;
2304
2305         format_state = modest_msg_edit_window_get_format_state (window);
2306         g_return_if_fail (format_state != NULL);
2307
2308         format_state->bold = gtk_toggle_action_get_active (action);
2309         modest_msg_edit_window_set_format_state (window, format_state);
2310         g_free (format_state);
2311         
2312 }
2313
2314 void 
2315 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2316                                      ModestMsgEditWindow *window)
2317 {
2318         ModestMsgEditFormatState *format_state = NULL;
2319
2320         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2321         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2322
2323         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2324                 return;
2325
2326         format_state = modest_msg_edit_window_get_format_state (window);
2327         g_return_if_fail (format_state != NULL);
2328
2329         format_state->italics = gtk_toggle_action_get_active (action);
2330         modest_msg_edit_window_set_format_state (window, format_state);
2331         g_free (format_state);
2332         
2333 }
2334
2335 void 
2336 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2337                                      ModestMsgEditWindow *window)
2338 {
2339         ModestMsgEditFormatState *format_state = NULL;
2340
2341         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2342         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2343
2344         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2345                 return;
2346
2347         format_state = modest_msg_edit_window_get_format_state (window);
2348         g_return_if_fail (format_state != NULL);
2349
2350         format_state->bullet = gtk_toggle_action_get_active (action);
2351         modest_msg_edit_window_set_format_state (window, format_state);
2352         g_free (format_state);
2353         
2354 }
2355
2356 void 
2357 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2358                                      GtkRadioAction *selected,
2359                                      ModestMsgEditWindow *window)
2360 {
2361         ModestMsgEditFormatState *format_state = NULL;
2362         GtkJustification value;
2363
2364         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2365
2366         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2367                 return;
2368
2369         value = gtk_radio_action_get_current_value (selected);
2370
2371         format_state = modest_msg_edit_window_get_format_state (window);
2372         g_return_if_fail (format_state != NULL);
2373
2374         format_state->justification = value;
2375         modest_msg_edit_window_set_format_state (window, format_state);
2376         g_free (format_state);
2377 }
2378
2379 void 
2380 modest_ui_actions_on_select_editor_color (GtkAction *action,
2381                                           ModestMsgEditWindow *window)
2382 {
2383         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2384         g_return_if_fail (GTK_IS_ACTION (action));
2385
2386         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2387                 return;
2388
2389         modest_msg_edit_window_select_color (window);
2390 }
2391
2392 void 
2393 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2394                                                      ModestMsgEditWindow *window)
2395 {
2396         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2397         g_return_if_fail (GTK_IS_ACTION (action));
2398
2399         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2400                 return;
2401
2402         modest_msg_edit_window_select_background_color (window);
2403 }
2404
2405 void 
2406 modest_ui_actions_on_insert_image (GtkAction *action,
2407                                    ModestMsgEditWindow *window)
2408 {
2409         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2410         g_return_if_fail (GTK_IS_ACTION (action));
2411
2412         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2413                 return;
2414
2415         modest_msg_edit_window_insert_image (window);
2416 }
2417
2418 void 
2419 modest_ui_actions_on_attach_file (GtkAction *action,
2420                                   ModestMsgEditWindow *window)
2421 {
2422         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2423         g_return_if_fail (GTK_IS_ACTION (action));
2424
2425         modest_msg_edit_window_offer_attach_file (window);
2426 }
2427
2428 void 
2429 modest_ui_actions_on_remove_attachments (GtkAction *action,
2430                                          ModestMsgEditWindow *window)
2431 {
2432         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2433         g_return_if_fail (GTK_IS_ACTION (action));
2434
2435         modest_msg_edit_window_remove_attachments (window, NULL);
2436 }
2437
2438 static void
2439 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2440                                             gpointer user_data)
2441 {
2442         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2443         const GError *error = modest_mail_operation_get_error (mail_op);
2444
2445         if(error) {
2446                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2447                                                     _("mail_in_ui_folder_create_error"));
2448         }
2449 }
2450
2451 static void
2452 modest_ui_actions_create_folder(GtkWidget *parent_window,
2453                                 GtkWidget *folder_view)
2454 {
2455         TnyFolderStore *parent_folder;
2456
2457         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2458         
2459         if (parent_folder) {
2460                 gboolean finished = FALSE;
2461                 gint result;
2462                 gchar *folder_name = NULL, *suggested_name = NULL;
2463                 const gchar *proto_str = NULL;
2464                 TnyAccount *account;
2465
2466                 if (TNY_IS_ACCOUNT (parent_folder))
2467                         account = g_object_ref (parent_folder);
2468                 else
2469                         account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2470                 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2471
2472                 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2473                     MODEST_PROTOCOL_STORE_POP) {
2474                         finished = TRUE;
2475                         hildon_banner_show_information (NULL, NULL, _("mail_in_ui_folder_create_error"));
2476                 }
2477                 g_object_unref (account);
2478
2479                 /* Run the new folder dialog */
2480                 while (!finished) {
2481                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2482                                                                         parent_folder,
2483                                                                         suggested_name,
2484                                                                         &folder_name);
2485
2486                         g_free (suggested_name);
2487                         suggested_name = NULL;
2488
2489                         if (result == GTK_RESPONSE_REJECT) {
2490                                 finished = TRUE;
2491                         } else {
2492                                 ModestMailOperation *mail_op;
2493                                 TnyFolder *new_folder = NULL;
2494
2495                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2496                                                                                           G_OBJECT(parent_window),
2497                                                                                           modest_ui_actions_new_folder_error_handler,
2498                                                                                           parent_window);
2499
2500                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2501                                                                  mail_op);
2502                                 new_folder = modest_mail_operation_create_folder (mail_op,
2503                                                                                   parent_folder,
2504                                                                                   (const gchar *) folder_name);
2505                                 if (new_folder) {
2506                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2507                                                                           new_folder, TRUE);
2508
2509                                         g_object_unref (new_folder);
2510                                         finished = TRUE;
2511                                 }
2512                                 g_object_unref (mail_op);
2513                         }
2514
2515                         suggested_name = folder_name;
2516                         folder_name = NULL;
2517                 }
2518
2519                 g_object_unref (parent_folder);
2520         }
2521 }
2522
2523 void 
2524 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2525 {
2526         GtkWidget *folder_view;
2527         
2528         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2529
2530         folder_view = modest_main_window_get_child_widget (main_window,
2531                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2532         if (!folder_view)
2533                 return;
2534
2535         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2536 }
2537
2538 static void
2539 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2540                                                gpointer user_data)
2541 {
2542         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2543         const GError *error = NULL;
2544         const gchar *message = NULL;
2545         
2546         /* Get error message */
2547         error = modest_mail_operation_get_error (mail_op);
2548         if (!error)
2549                 g_return_if_reached ();
2550
2551         switch (error->code) {
2552         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2553                 message = _CS("ckdg_ib_folder_already_exists");
2554                 break;
2555         default:
2556                 g_return_if_reached ();
2557         }
2558
2559         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2560 }
2561
2562 void 
2563 modest_ui_actions_on_rename_folder (GtkAction *action,
2564                                      ModestMainWindow *main_window)
2565 {
2566         TnyFolderStore *folder;
2567         GtkWidget *folder_view;
2568         GtkWidget *header_view; 
2569
2570         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2571
2572         folder_view = modest_main_window_get_child_widget (main_window,
2573                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2574         if (!folder_view)
2575                 return;
2576
2577         header_view = modest_main_window_get_child_widget (main_window,
2578                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2579         
2580         if (!header_view)
2581                 return;
2582
2583         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2584
2585         if (!folder)
2586                 return;
2587
2588         if (TNY_IS_FOLDER (folder)) {
2589                 gchar *folder_name;
2590                 gint response;
2591                 const gchar *current_name;
2592                 TnyFolderStore *parent;
2593                 gboolean do_rename = TRUE;
2594
2595                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2596                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2597                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2598                                                                      parent, current_name, 
2599                                                                      &folder_name);
2600                 g_object_unref (parent);
2601
2602                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2603                         do_rename = FALSE;
2604                 } else if (modest_platform_is_network_folderstore(folder) &&
2605                            !tny_device_is_online (modest_runtime_get_device())) {
2606                         TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2607                         do_rename = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2608                         g_object_unref(account);
2609                 }
2610
2611                 if (do_rename) {
2612                         ModestMailOperation *mail_op;
2613                         GtkTreeSelection *sel = NULL;
2614
2615                         mail_op = 
2616                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2617                                                                                G_OBJECT(main_window),
2618                                                                                modest_ui_actions_rename_folder_error_handler,
2619                                                                                main_window);
2620
2621                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2622                                                          mail_op);
2623
2624                         /* Clear the headers view */
2625                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2626                         gtk_tree_selection_unselect_all (sel);
2627
2628                         /* Select *after* the changes */
2629                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2630                                                           TNY_FOLDER(folder), TRUE);
2631
2632                         /* Actually rename the folder */
2633                         modest_mail_operation_rename_folder (mail_op,
2634                                                              TNY_FOLDER (folder),
2635                                                              (const gchar *) folder_name);
2636
2637                         g_object_unref (mail_op);
2638                         g_free (folder_name);
2639                 }
2640         }
2641         g_object_unref (folder);
2642 }
2643
2644 static void
2645 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2646                                                gpointer user_data)
2647 {
2648         GObject *win = modest_mail_operation_get_source (mail_op);
2649
2650         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2651                                                 _("mail_in_ui_folder_delete_error"));
2652         g_object_unref (win);
2653 }
2654
2655 static gboolean
2656 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2657 {
2658         TnyFolderStore *folder;
2659         GtkWidget *folder_view;
2660         gint response;
2661         gchar *message;
2662         gboolean do_delete = TRUE;
2663
2664         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (main_window), FALSE);
2665
2666         folder_view = modest_main_window_get_child_widget (main_window,
2667                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2668         if (!folder_view)
2669                 return FALSE;
2670
2671         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2672
2673         /* Show an error if it's an account */
2674         if (!TNY_IS_FOLDER (folder)) {
2675                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2676                                                         _("mail_in_ui_folder_delete_error"));
2677                 g_object_unref (G_OBJECT (folder));
2678                 return FALSE;
2679         }
2680
2681         /* Ask the user */      
2682         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2683                                     tny_folder_get_name (TNY_FOLDER (folder)));
2684         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2685                                                             (const gchar *) message);
2686         g_free (message);
2687
2688         if (response != GTK_RESPONSE_OK) {
2689                 do_delete = FALSE;
2690         } else if (modest_platform_is_network_folderstore(folder) &&
2691                    !tny_device_is_online (modest_runtime_get_device())) {
2692                 TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2693                 do_delete = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2694                 g_object_unref(account);
2695         }
2696
2697         if (do_delete) {
2698                 ModestMailOperation *mail_op;
2699                 GtkTreeSelection *sel;
2700
2701                 /* Unselect the folder before deleting it to free the headers */
2702                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2703                 gtk_tree_selection_unselect_all (sel);
2704
2705                 /* Create the mail operation */
2706                 mail_op =
2707                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2708                                                                        G_OBJECT(main_window),
2709                                                                        modest_ui_actions_delete_folder_error_handler,
2710                                                                        NULL);
2711
2712                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2713                                                  mail_op);
2714                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2715                 g_object_unref (G_OBJECT (mail_op));
2716         }
2717
2718         g_object_unref (G_OBJECT (folder));
2719
2720         return do_delete;
2721 }
2722
2723 void 
2724 modest_ui_actions_on_delete_folder (GtkAction *action,
2725                                      ModestMainWindow *main_window)
2726 {
2727         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2728
2729         if (delete_folder (main_window, FALSE)) {
2730                 GtkWidget *folder_view;
2731
2732                 folder_view = modest_main_window_get_child_widget (main_window,
2733                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2734                 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2735         }
2736 }
2737
2738 void 
2739 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2740 {
2741         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2742         
2743         delete_folder (main_window, TRUE);
2744 }
2745
2746
2747 static void
2748 show_error (GtkWidget *parent_widget, const gchar* text)
2749 {
2750         hildon_banner_show_information(parent_widget, NULL, text);
2751         
2752 #if 0
2753         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2754         /*
2755           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2756           (GtkDialogFlags)0,
2757           GTK_MESSAGE_ERROR,
2758           GTK_BUTTONS_OK,
2759           text ));
2760         */
2761                  
2762         gtk_dialog_run (dialog);
2763         gtk_widget_destroy (GTK_WIDGET (dialog));
2764 #endif
2765 }
2766
2767 void
2768 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2769                                          const gchar* server_account_name,
2770                                          gchar **username,
2771                                          gchar **password, 
2772                                          gboolean *cancel, 
2773                                          gboolean *remember,
2774                                          ModestMainWindow *main_window)
2775 {
2776         g_return_if_fail(server_account_name);
2777         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2778         
2779         /* Initalize output parameters: */
2780         if (cancel)
2781                 *cancel = FALSE;
2782                 
2783         if (remember)
2784                 *remember = TRUE;
2785                 
2786 #ifdef MODEST_PLATFORM_MAEMO
2787         /* Maemo uses a different (awkward) button order,
2788          * It should probably just use gtk_alternative_dialog_button_order ().
2789          */
2790         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2791                                               NULL,
2792                                               GTK_DIALOG_MODAL,
2793                                               _("mcen_bd_dialog_ok"),
2794                                               GTK_RESPONSE_ACCEPT,
2795                                               _("mcen_bd_dialog_cancel"),
2796                                               GTK_RESPONSE_REJECT,
2797                                               NULL);
2798 #else
2799         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2800                                               NULL,
2801                                               GTK_DIALOG_MODAL,
2802                                               GTK_STOCK_CANCEL,
2803                                               GTK_RESPONSE_REJECT,
2804                                               GTK_STOCK_OK,
2805                                               GTK_RESPONSE_ACCEPT,
2806                                               NULL);
2807 #endif /* MODEST_PLATFORM_MAEMO */
2808
2809         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2810         
2811         gchar *server_name = modest_server_account_get_hostname (
2812                 modest_runtime_get_account_mgr(), server_account_name);
2813         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2814                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2815                 *cancel = TRUE;
2816                 return;
2817         }
2818         
2819         /* This causes a warning because the logical ID has no %s in it, 
2820          * though the translation does, but there is not much we can do about that: */
2821         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2822         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2823                             FALSE, FALSE, 0);
2824         g_free (txt);
2825         g_free (server_name);
2826         server_name = NULL;
2827
2828         /* username: */
2829         gchar *initial_username = modest_server_account_get_username (
2830                 modest_runtime_get_account_mgr(), server_account_name);
2831         
2832         GtkWidget *entry_username = gtk_entry_new ();
2833         if (initial_username)
2834                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2835         /* Dim this if a connection has ever succeeded with this username,
2836          * as per the UI spec: */
2837         const gboolean username_known = 
2838                 modest_server_account_get_username_has_succeeded(
2839                         modest_runtime_get_account_mgr(), server_account_name);
2840         gtk_widget_set_sensitive (entry_username, !username_known);
2841         
2842 #ifdef MODEST_PLATFORM_MAEMO
2843         /* Auto-capitalization is the default, so let's turn it off: */
2844         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2845         
2846         /* Create a size group to be used by all captions.
2847          * Note that HildonCaption does not create a default size group if we do not specify one.
2848          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2849         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2850         
2851         GtkWidget *caption = hildon_caption_new (sizegroup, 
2852                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2853         gtk_widget_show (entry_username);
2854         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2855                 FALSE, FALSE, MODEST_MARGIN_HALF);
2856         gtk_widget_show (caption);
2857 #else 
2858         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2859                             TRUE, FALSE, 0);
2860 #endif /* MODEST_PLATFORM_MAEMO */      
2861                             
2862         /* password: */
2863         GtkWidget *entry_password = gtk_entry_new ();
2864         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2865         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2866         
2867 #ifdef MODEST_PLATFORM_MAEMO
2868         /* Auto-capitalization is the default, so let's turn it off: */
2869         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2870                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2871         
2872         caption = hildon_caption_new (sizegroup, 
2873                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2874         gtk_widget_show (entry_password);
2875         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2876                 FALSE, FALSE, MODEST_MARGIN_HALF);
2877         gtk_widget_show (caption);
2878         g_object_unref (sizegroup);
2879 #else 
2880         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2881                             TRUE, FALSE, 0);
2882 #endif /* MODEST_PLATFORM_MAEMO */      
2883
2884         if (initial_username != NULL)
2885                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
2886                                 
2887 /* This is not in the Maemo UI spec:
2888         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2889         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2890                             TRUE, FALSE, 0);
2891 */
2892
2893         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2894         
2895         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2896                 if (username) {
2897                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2898                         
2899                         modest_server_account_set_username (
2900                                  modest_runtime_get_account_mgr(), server_account_name, 
2901                                  *username);
2902                                  
2903                         const gboolean username_was_changed = 
2904                                 (strcmp (*username, initial_username) != 0);
2905                         if (username_was_changed) {
2906                                 g_warning ("%s: tinymail does not yet support changing the "
2907                                         "username in the get_password() callback.\n", __FUNCTION__);
2908                         }
2909                 }
2910                         
2911                 if (password) {
2912                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2913                         
2914                         /* We do not save the password in the configuration, 
2915                          * because this function is only called for passwords that should 
2916                          * not be remembered:
2917                         modest_server_account_set_password (
2918                                  modest_runtime_get_account_mgr(), server_account_name, 
2919                                  *password);
2920                         */
2921                 }
2922                 
2923                 if (cancel)
2924                         *cancel   = FALSE;
2925                         
2926         } else {
2927                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2928                 
2929                 if (username)
2930                         *username = NULL;
2931                         
2932                 if (password)
2933                         *password = NULL;
2934                         
2935                 if (cancel)
2936                         *cancel   = TRUE;
2937         }
2938
2939 /* This is not in the Maemo UI spec:
2940         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2941                 *remember = TRUE;
2942         else
2943                 *remember = FALSE;
2944 */
2945
2946         gtk_widget_destroy (dialog);
2947         
2948         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2949 }
2950
2951 void
2952 modest_ui_actions_on_cut (GtkAction *action,
2953                           ModestWindow *window)
2954 {
2955         GtkWidget *focused_widget;
2956         GtkClipboard *clipboard;
2957
2958         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2959         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2960         if (GTK_IS_EDITABLE (focused_widget)) {
2961                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2962                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2963                 gtk_clipboard_store (clipboard);
2964         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2965                 GtkTextBuffer *buffer;
2966
2967                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2968                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2969                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2970                 gtk_clipboard_store (clipboard);
2971         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2972                 TnyList *header_list = modest_header_view_get_selected_headers (
2973                                 MODEST_HEADER_VIEW (focused_widget));
2974                 gboolean continue_download = FALSE;
2975                 gint num_of_unc_msgs;
2976
2977                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
2978
2979                 if (num_of_unc_msgs)
2980                         continue_download = connect_to_get_msg(
2981                                                                 GTK_WINDOW (window),
2982                                                                 num_of_unc_msgs);
2983
2984                 if (num_of_unc_msgs == 0 || continue_download) {
2985 /*                      modest_platform_information_banner (
2986                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
2987                         modest_header_view_cut_selection (
2988                                         MODEST_HEADER_VIEW (focused_widget));
2989                 }
2990
2991                 g_object_unref (header_list);
2992         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2993                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2994         }
2995 }
2996
2997 void
2998 modest_ui_actions_on_copy (GtkAction *action,
2999                            ModestWindow *window)
3000 {
3001         GtkClipboard *clipboard;
3002         GtkWidget *focused_widget;
3003         gboolean copied = TRUE;
3004
3005         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3006         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3007
3008         if (GTK_IS_LABEL (focused_widget)) {
3009                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
3010                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3011                 gtk_clipboard_store (clipboard);
3012         } else if (GTK_IS_EDITABLE (focused_widget)) {
3013                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3014                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3015                 gtk_clipboard_store (clipboard);
3016         } else if (GTK_IS_HTML (focused_widget)) {
3017                 gtk_html_copy (GTK_HTML (focused_widget));
3018                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3019                 gtk_clipboard_store (clipboard);
3020         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3021                 GtkTextBuffer *buffer;
3022                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3023                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3024                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3025                 gtk_clipboard_store (clipboard);
3026         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3027                 TnyList *header_list = modest_header_view_get_selected_headers (
3028                                 MODEST_HEADER_VIEW (focused_widget));
3029                 gboolean continue_download = FALSE;
3030                 gint num_of_unc_msgs;
3031
3032                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3033
3034                 if (num_of_unc_msgs)
3035                         continue_download = connect_to_get_msg(
3036                                                                 GTK_WINDOW (window),
3037                                                                 num_of_unc_msgs);
3038
3039                 if (num_of_unc_msgs == 0 || continue_download) {
3040                         modest_platform_information_banner (
3041                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3042                         modest_header_view_copy_selection (
3043                                         MODEST_HEADER_VIEW (focused_widget));
3044                 } else
3045                         copied = FALSE;
3046
3047                 g_object_unref (header_list);
3048
3049         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3050                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3051         }
3052
3053         /* Show information banner if there was a copy to clipboard */
3054         if(copied)
3055                 modest_platform_information_banner (
3056                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3057 }
3058
3059 void
3060 modest_ui_actions_on_undo (GtkAction *action,
3061                            ModestWindow *window)
3062 {
3063         ModestEmailClipboard *clipboard = NULL;
3064
3065         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3066                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3067         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3068                 /* Clear clipboard source */
3069                 clipboard = modest_runtime_get_email_clipboard ();
3070                 modest_email_clipboard_clear (clipboard);               
3071         }
3072         else {
3073                 g_return_if_reached ();
3074         }
3075 }
3076
3077 void
3078 modest_ui_actions_on_redo (GtkAction *action,
3079                            ModestWindow *window)
3080 {
3081         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3082                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3083         }
3084         else {
3085                 g_return_if_reached ();
3086         }
3087 }
3088
3089
3090 static void
3091 destroy_information_note (ModestMailOperation *mail_op, gpointer user_data)
3092 {
3093         /* destroy information note */
3094         gtk_widget_destroy (GTK_WIDGET(user_data));
3095 }
3096
3097
3098 static void
3099 paste_as_attachment_free (gpointer data)
3100 {
3101         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3102
3103         gtk_widget_destroy (helper->banner);
3104         g_object_unref (helper->banner);
3105         g_free (helper);
3106 }
3107
3108 static void
3109 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3110                             TnyHeader *header,
3111                             TnyMsg *msg,
3112                             gpointer userdata)
3113 {
3114         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3115         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3116
3117         if (msg == NULL)
3118                 return;
3119
3120         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3121         
3122 }
3123
3124 void
3125 modest_ui_actions_on_paste (GtkAction *action,
3126                             ModestWindow *window)
3127 {
3128         GtkWidget *focused_widget = NULL;
3129         GtkWidget *inf_note = NULL;
3130         ModestMailOperation *mail_op = NULL;
3131
3132         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3133         if (GTK_IS_EDITABLE (focused_widget)) {
3134                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3135         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3136                 ModestEmailClipboard *e_clipboard = NULL;
3137                 e_clipboard = modest_runtime_get_email_clipboard ();
3138                 if (modest_email_clipboard_cleared (e_clipboard)) {
3139                         GtkTextBuffer *buffer;
3140                         GtkClipboard *clipboard;
3141
3142                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3143                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3144                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3145                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3146                         ModestMailOperation *mail_op;
3147                         TnyFolder *src_folder;
3148                         TnyList *data;
3149                         gboolean delete;
3150                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3151                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3152                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3153                                                                            _CS("ckct_nw_pasting"));
3154                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3155                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3156                                                              G_OBJECT (window));
3157                         if (helper->banner != NULL) {
3158                                 g_object_ref (G_OBJECT (helper->banner));
3159                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3160                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3161                         }
3162
3163                         if (data != NULL) {
3164                                 modest_mail_operation_get_msgs_full (mail_op, 
3165                                                                      data,
3166                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3167                                                                      helper,
3168                                                                      paste_as_attachment_free);
3169                         }
3170                 }
3171         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3172                 ModestEmailClipboard *clipboard = NULL;
3173                 TnyFolder *src_folder = NULL;
3174                 TnyFolderStore *folder_store = NULL;
3175                 TnyList *data = NULL;           
3176                 gboolean delete = FALSE;
3177                 
3178                 /* Check clipboard source */
3179                 clipboard = modest_runtime_get_email_clipboard ();
3180                 if (modest_email_clipboard_cleared (clipboard)) 
3181                         return;
3182                 
3183                 /* Get elements to paste */
3184                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3185
3186                 /* Create a new mail operation */
3187                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
3188                 
3189                 /* Get destination folder */
3190                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3191
3192                 /* transfer messages  */
3193                 if (data != NULL) {
3194                         gint response = 0;
3195
3196                         /* Ask for user confirmation */
3197                         response = 
3198                                 modest_ui_actions_msgs_move_to_confirmation (GTK_WINDOW (window), 
3199                                                                              TNY_FOLDER (folder_store), 
3200                                                                              delete,
3201                                                                              data);
3202                         
3203                         if (response == GTK_RESPONSE_OK) {
3204                                 /* Launch notification */
3205                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3206                                                                              _CS("ckct_nw_pasting"));
3207                                 if (inf_note != NULL)  {
3208                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3209                                         gtk_widget_show (GTK_WIDGET(inf_note));
3210                                 }
3211
3212                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3213                                 modest_mail_operation_xfer_msgs (mail_op, 
3214                                                                  data,
3215                                                                  TNY_FOLDER (folder_store),
3216                                                                  delete,
3217                                                                  destroy_information_note,
3218                                                                  inf_note);                             
3219                         } else {
3220                                 g_object_unref (mail_op);
3221                         }
3222                         
3223                 } else if (src_folder != NULL) {                        
3224                         /* Launch notification */
3225                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3226                                                                      _CS("ckct_nw_pasting"));
3227                         if (inf_note != NULL)  {
3228                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3229                                 gtk_widget_show (GTK_WIDGET(inf_note));
3230                         }
3231                         
3232                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3233                         modest_mail_operation_xfer_folder (mail_op, 
3234                                                            src_folder,
3235                                                            folder_store,
3236                                                            delete,
3237                                                            destroy_information_note,
3238                                                            inf_note);
3239                 }
3240
3241                 /* Free */
3242                 if (data != NULL) 
3243                         g_object_unref (data);
3244                 if (src_folder != NULL) 
3245                         g_object_unref (src_folder);
3246                 if (folder_store != NULL) 
3247                         g_object_unref (folder_store);
3248         }
3249 }
3250
3251
3252 void
3253 modest_ui_actions_on_select_all (GtkAction *action,
3254                                  ModestWindow *window)
3255 {
3256         GtkWidget *focused_widget;
3257
3258         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3259         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3260                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3261         } else if (GTK_IS_LABEL (focused_widget)) {
3262                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3263         } else if (GTK_IS_EDITABLE (focused_widget)) {
3264                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3265         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3266                 GtkTextBuffer *buffer;
3267                 GtkTextIter start, end;
3268
3269                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3270                 gtk_text_buffer_get_start_iter (buffer, &start);
3271                 gtk_text_buffer_get_end_iter (buffer, &end);
3272                 gtk_text_buffer_select_range (buffer, &start, &end);
3273         } else if (GTK_IS_HTML (focused_widget)) {
3274                 gtk_html_select_all (GTK_HTML (focused_widget));
3275         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3276                 GtkWidget *header_view = focused_widget;
3277                 GtkTreeSelection *selection = NULL;
3278                 
3279                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3280                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3281                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3282                 }
3283                                 
3284                 /* Disable window dimming management */
3285                 modest_window_disable_dimming (MODEST_WINDOW(window));
3286                 
3287                 /* Select all messages */
3288                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3289                 gtk_tree_selection_select_all (selection);
3290
3291                 /* Set focuse on header view */
3292                 gtk_widget_grab_focus (header_view);
3293
3294
3295                 /* Enable window dimming management */
3296                 modest_window_enable_dimming (MODEST_WINDOW(window));
3297                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3298         }
3299
3300 }
3301
3302 void
3303 modest_ui_actions_on_mark_as_read (GtkAction *action,
3304                                    ModestWindow *window)
3305 {       
3306         g_return_if_fail (MODEST_IS_WINDOW(window));
3307                 
3308         /* Mark each header as read */
3309         do_headers_action (window, headers_action_mark_as_read, NULL);
3310 }
3311
3312 void
3313 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3314                                      ModestWindow *window)
3315 {       
3316         g_return_if_fail (MODEST_IS_WINDOW(window));
3317                 
3318         /* Mark each header as read */
3319         do_headers_action (window, headers_action_mark_as_unread, NULL);
3320 }
3321
3322 void
3323 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3324                                   GtkRadioAction *selected,
3325                                   ModestWindow *window)
3326 {
3327         gint value;
3328
3329         value = gtk_radio_action_get_current_value (selected);
3330         if (MODEST_IS_WINDOW (window)) {
3331                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3332         }
3333 }
3334
3335 void     
3336 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3337                                                GtkRadioAction *selected,
3338                                                ModestWindow *window)
3339 {
3340         TnyHeaderFlags flags;
3341         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3342
3343         flags = gtk_radio_action_get_current_value (selected);
3344         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3345 }
3346
3347 void     
3348 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3349                                                   GtkRadioAction *selected,
3350                                                   ModestWindow *window)
3351 {
3352         gint file_format;
3353
3354         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3355
3356         file_format = gtk_radio_action_get_current_value (selected);
3357         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3358 }
3359
3360
3361 void     
3362 modest_ui_actions_on_zoom_plus (GtkAction *action,
3363                                 ModestWindow *window)
3364 {
3365         g_return_if_fail (MODEST_IS_WINDOW (window));
3366
3367         modest_window_zoom_plus (MODEST_WINDOW (window));
3368 }
3369
3370 void     
3371 modest_ui_actions_on_zoom_minus (GtkAction *action,
3372                                  ModestWindow *window)
3373 {
3374         g_return_if_fail (MODEST_IS_WINDOW (window));
3375
3376         modest_window_zoom_minus (MODEST_WINDOW (window));
3377 }
3378
3379 void     
3380 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3381                                            ModestWindow *window)
3382 {
3383         ModestWindowMgr *mgr;
3384         gboolean fullscreen, active;
3385         g_return_if_fail (MODEST_IS_WINDOW (window));
3386
3387         mgr = modest_runtime_get_window_mgr ();
3388
3389         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3390         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3391
3392         if (active != fullscreen) {
3393                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3394                 gtk_window_present (GTK_WINDOW (window));
3395         }
3396 }
3397
3398 void
3399 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3400                                         ModestWindow *window)
3401 {
3402         ModestWindowMgr *mgr;
3403         gboolean fullscreen;
3404
3405         g_return_if_fail (MODEST_IS_WINDOW (window));
3406
3407         mgr = modest_runtime_get_window_mgr ();
3408         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3409         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3410
3411         gtk_window_present (GTK_WINDOW (window));
3412 }
3413
3414 /* 
3415  * Used by modest_ui_actions_on_details to call do_headers_action 
3416  */
3417 static void
3418 headers_action_show_details (TnyHeader *header, 
3419                              ModestWindow *window,
3420                              gpointer user_data)
3421
3422 {
3423         GtkWidget *dialog;
3424         
3425         /* Create dialog */
3426         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3427
3428         /* Run dialog */
3429         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3430         gtk_widget_show_all (dialog);
3431         gtk_dialog_run (GTK_DIALOG (dialog));
3432
3433         gtk_widget_destroy (dialog);
3434 }
3435
3436 /*
3437  * Show the folder details in a ModestDetailsDialog widget
3438  */
3439 static void
3440 show_folder_details (TnyFolder *folder, 
3441                      GtkWindow *window)
3442 {
3443         GtkWidget *dialog;
3444         
3445         /* Create dialog */
3446         dialog = modest_details_dialog_new_with_folder (window, folder);
3447
3448         /* Run dialog */
3449         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3450         gtk_widget_show_all (dialog);
3451         gtk_dialog_run (GTK_DIALOG (dialog));
3452
3453         gtk_widget_destroy (dialog);
3454 }
3455
3456 /*
3457  * Show the header details in a ModestDetailsDialog widget
3458  */
3459 void     
3460 modest_ui_actions_on_details (GtkAction *action, 
3461                               ModestWindow *win)
3462 {
3463         TnyList * headers_list;
3464         TnyIterator *iter;
3465         TnyHeader *header;              
3466
3467         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3468                 TnyMsg *msg;
3469
3470                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3471                 if (!msg)
3472                         return;
3473                 g_object_unref (msg);           
3474
3475                 headers_list = get_selected_headers (win);
3476                 if (!headers_list)
3477                         return;
3478
3479                 iter = tny_list_create_iterator (headers_list);
3480
3481                 header = TNY_HEADER (tny_iterator_get_current (iter));
3482                 if (header) {
3483                         headers_action_show_details (header, win, NULL);
3484                         g_object_unref (header);
3485                 }
3486
3487                 g_object_unref (iter);
3488                 g_object_unref (headers_list);
3489
3490         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3491                 GtkWidget *folder_view, *header_view;
3492
3493                 /* Check which widget has the focus */
3494                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3495                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3496                 if (gtk_widget_is_focus (folder_view)) {
3497                         TnyFolderStore *folder_store
3498                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3499                         if (!folder_store) {
3500                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3501                                 return; 
3502                         }
3503                         /* Show only when it's a folder */
3504                         /* This function should not be called for account items, 
3505                          * because we dim the menu item for them. */
3506                         if (TNY_IS_FOLDER (folder_store)) {
3507                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3508                         }
3509
3510                         g_object_unref (folder_store);
3511
3512                 } else {
3513                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3514                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3515                         /* Show details of each header */
3516                         do_headers_action (win, headers_action_show_details, header_view);
3517                 }
3518         }
3519 }
3520
3521 void     
3522 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3523                                      ModestMsgEditWindow *window)
3524 {
3525         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3526
3527         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3528 }
3529
3530 void     
3531 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3532                                       ModestMsgEditWindow *window)
3533 {
3534         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3535
3536         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3537 }
3538
3539 void
3540 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3541                                        ModestMainWindow *main_window)
3542 {
3543         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3544
3545         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3546                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3547         else
3548                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3549 }
3550
3551 void 
3552 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3553                                      ModestWindow *window)
3554 {
3555         gboolean active, fullscreen = FALSE;
3556         ModestWindowMgr *mgr;
3557
3558         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3559
3560         /* Check if we want to toggle the toolbar vuew in fullscreen
3561            or normal mode */
3562         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3563                      "ViewShowToolbarFullScreen")) {
3564                 fullscreen = TRUE;
3565         }
3566
3567         /* Toggle toolbar */
3568         mgr = modest_runtime_get_window_mgr ();
3569         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3570 }
3571
3572 void     
3573 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3574                                            ModestMsgEditWindow *window)
3575 {
3576         modest_msg_edit_window_select_font (window);
3577 }
3578
3579 void
3580 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3581                                                   const gchar *display_name,
3582                                                   GtkWindow *window)
3583 {
3584         /* Do not change the application name if the widget has not
3585            the focus. This callback could be called even if the folder
3586            view has not the focus, because the handled signal could be
3587            emitted when the folder view is redrawn */
3588         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3589                 if (display_name)
3590                         gtk_window_set_title (window, display_name);
3591                 else
3592                         gtk_window_set_title (window, " ");
3593         }
3594 }
3595
3596 void
3597 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3598 {
3599         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3600         modest_msg_edit_window_select_contacts (window);
3601 }
3602
3603 void
3604 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3605 {
3606         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3607         modest_msg_edit_window_check_names (window, FALSE);
3608 }
3609
3610 static void
3611 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3612 {
3613         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3614                                          GTK_WIDGET (user_data));
3615 }
3616
3617 /*
3618  * This function is used to track changes in the selection of the
3619  * folder view that is inside the "move to" dialog to enable/disable
3620  * the OK button because we do not want the user to select a disallowed
3621  * destination for a folder.
3622  * The user also not desired to be able to use NEW button on items where
3623  * folder creation is not possibel.
3624  */
3625 static void
3626 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3627                                             TnyFolderStore *folder_store,
3628                                             gboolean selected,
3629                                             gpointer user_data)
3630 {
3631         GtkWidget *dialog = NULL;
3632         GtkWidget *ok_button = NULL, *new_button = NULL;
3633         GList *children = NULL;
3634         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3635         gboolean moving_folder = FALSE;
3636         gboolean is_local_account = TRUE;
3637         GtkWidget *folder_view = NULL;
3638         ModestTnyFolderRules rules;
3639
3640         if (!selected)
3641                 return;
3642
3643         /* Get the OK button */
3644         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3645         if (!dialog)
3646                 return;
3647
3648         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3649         ok_button = GTK_WIDGET (children->next->next->data);
3650         new_button = GTK_WIDGET (children->next->data);
3651         g_list_free (children);
3652
3653         /* check if folder_store is an remote account */
3654         if (TNY_IS_ACCOUNT (folder_store)) {
3655                 TnyAccount *local_account = NULL;
3656                 ModestTnyAccountStore *account_store = NULL;
3657
3658                 account_store = modest_runtime_get_account_store ();
3659                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3660
3661                 if ((gpointer) local_account != (gpointer) folder_store) {
3662                         is_local_account = FALSE;
3663                         /* New button should be dimmed on remote
3664                            account root */
3665                         new_sensitive = FALSE;
3666                 }
3667                 g_object_unref (local_account);
3668         }
3669
3670         /* Check the target folder rules */
3671         if (TNY_IS_FOLDER (folder_store)) {
3672                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3673                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3674                         ok_sensitive = FALSE;
3675                         new_sensitive = FALSE;
3676                         goto end;
3677                 }
3678         }
3679
3680         /* Check if we're moving a folder */
3681         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3682                 /* Get the widgets */
3683                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3684                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3685                 if (gtk_widget_is_focus (folder_view))
3686                         moving_folder = TRUE;
3687         }
3688
3689         if (moving_folder) {
3690                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3691
3692                 /* Get the folder to move */
3693                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3694                 
3695                 /* Check that we're not moving to the same folder */
3696                 if (TNY_IS_FOLDER (moved_folder)) {
3697                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3698                         if (parent == folder_store)
3699                                 ok_sensitive = FALSE;
3700                         g_object_unref (parent);
3701                 } 
3702
3703                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3704                         /* Do not allow to move to an account unless it's the
3705                            local folders account */
3706                         if (!is_local_account)
3707                                 ok_sensitive = FALSE;
3708                 } 
3709
3710                 if (ok_sensitive && (moved_folder == folder_store)) {
3711                         /* Do not allow to move to itself */
3712                         ok_sensitive = FALSE;
3713                 }
3714                 g_object_unref (moved_folder);
3715         } else {
3716                 TnyHeader *header = NULL;
3717                 TnyFolder *src_folder = NULL;
3718
3719                 /* Moving a message */
3720                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3721                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3722                         src_folder = tny_header_get_folder (header);
3723                         g_object_unref (header);
3724                 } else {
3725                         src_folder = 
3726                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3727                 }
3728
3729                 /* Do not allow to move the msg to the same folder */
3730                 /* Do not allow to move the msg to an account */
3731                 if ((gpointer) src_folder == (gpointer) folder_store ||
3732                     TNY_IS_ACCOUNT (folder_store))
3733                         ok_sensitive = FALSE;
3734                 g_object_unref (src_folder);
3735         }
3736
3737  end:
3738         /* Set sensitivity of the OK button */
3739         gtk_widget_set_sensitive (ok_button, ok_sensitive);
3740         /* Set sensitivity of the NEW button */
3741         gtk_widget_set_sensitive (new_button, new_sensitive);
3742 }
3743
3744 static GtkWidget*
3745 create_move_to_dialog (GtkWindow *win,
3746                        GtkWidget *folder_view,
3747                        GtkWidget **tree_view)
3748 {
3749         GtkWidget *dialog, *scroll;
3750         GtkWidget *new_button;
3751
3752         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3753                                               GTK_WINDOW (win),
3754                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3755                                               NULL);
3756
3757         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3758         /* We do this manually so GTK+ does not associate a response ID for
3759          * the button. */
3760         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3761         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3762         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3763
3764         /* Create scrolled window */
3765         scroll = gtk_scrolled_window_new (NULL, NULL);
3766         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3767                                          GTK_POLICY_AUTOMATIC,
3768                                          GTK_POLICY_AUTOMATIC);
3769
3770         /* Create folder view */
3771         *tree_view = modest_platform_create_folder_view (NULL);
3772
3773         /* Track changes in the selection to
3774          * disable the OK button whenever "Move to" is not possible
3775          * disbale NEW button whenever New is not possible */
3776         g_signal_connect (*tree_view,
3777                           "folder_selection_changed",
3778                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3779                           win);
3780
3781         /* Listen to clicks on New button */
3782         g_signal_connect (G_OBJECT (new_button), 
3783                           "clicked", 
3784                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3785                           *tree_view);
3786
3787         /* It could happen that we're trying to move a message from a
3788            window (msg window for example) after the main window was
3789            closed, so we can not just get the model of the folder
3790            view */
3791         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3792                 const gchar *visible_id = NULL;
3793
3794                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3795                                                MODEST_FOLDER_VIEW(*tree_view));
3796
3797                 visible_id = 
3798                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3799
3800                 /* Show the same account than the one that is shown in the main window */
3801                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3802                                                                              visible_id);
3803         } else {
3804                 const gchar *active_account_name = NULL;
3805                 ModestAccountMgr *mgr = NULL;
3806                 ModestAccountData *acc_data = NULL;
3807
3808                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3809                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3810
3811                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3812                 mgr = modest_runtime_get_account_mgr ();
3813                 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3814
3815                 /* Set the new visible & active account */
3816                 if (acc_data && acc_data->store_account) { 
3817                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3818                                                                                      acc_data->store_account->account_name);
3819                         modest_account_mgr_free_account_data (mgr, acc_data);
3820                 }
3821         }
3822
3823         /* Hide special folders */
3824         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3825         
3826         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3827
3828         /* Add scroll to dialog */
3829         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3830                             scroll, TRUE, TRUE, 0);
3831
3832         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3833         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3834
3835         return dialog;
3836 }
3837
3838 /*
3839  * Returns TRUE if at least one of the headers of the list belongs to
3840  * a message that has been fully retrieved.
3841  */
3842 #if 0 /* no longer in use. delete in 2007.10 */
3843 static gboolean
3844 has_retrieved_msgs (TnyList *list)
3845 {
3846         TnyIterator *iter;
3847         gboolean found = FALSE;
3848
3849         iter = tny_list_create_iterator (list);
3850         while (!tny_iterator_is_done (iter) && !found) {
3851                 TnyHeader *header;
3852                 TnyHeaderFlags flags = 0;
3853
3854                 header = TNY_HEADER (tny_iterator_get_current (iter));
3855                 if (header) {
3856                         flags = tny_header_get_flags (header);
3857                         if (flags & TNY_HEADER_FLAG_CACHED)
3858 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3859                                 found = TRUE;
3860
3861                         g_object_unref (header);
3862                 }
3863
3864                 if (!found)
3865                         tny_iterator_next (iter);
3866         }
3867         g_object_unref (iter);
3868
3869         return found;
3870 }
3871 #endif /* 0 */
3872
3873
3874 /*
3875  * Shows a confirmation dialog to the user when we're moving messages
3876  * from a remote server to the local storage. Returns the dialog
3877  * response. If it's other kind of movement then it always returns
3878  * GTK_RESPONSE_OK
3879  *
3880  * This one is used by the next functions:
3881  *      modest_ui_actions_on_paste                      - commented out
3882  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
3883  */
3884 gint
3885 modest_ui_actions_msgs_move_to_confirmation (GtkWindow *win,
3886                                              TnyFolder *dest_folder,
3887                                              gboolean delete,
3888                                              TnyList *headers)
3889 {
3890         gint response = GTK_RESPONSE_OK;
3891
3892         /* return with OK if the destination is a remote folder */
3893         if (modest_tny_folder_is_remote_folder (dest_folder))
3894                 return GTK_RESPONSE_OK;
3895
3896         TnyFolder *src_folder = NULL;
3897         TnyIterator *iter = NULL;
3898         TnyHeader *header = NULL;
3899
3900         /* Get source folder */
3901         iter = tny_list_create_iterator (headers);
3902         header = TNY_HEADER (tny_iterator_get_current (iter));
3903         if (header) {
3904                 src_folder = tny_header_get_folder (header);
3905                 g_object_unref (header);
3906         }
3907         g_object_unref (iter);
3908
3909         /* if no src_folder, message may be an attahcment */
3910         if (src_folder == NULL) 
3911                 return GTK_RESPONSE_CANCEL;
3912
3913         /* If the source is a local or MMC folder */
3914         if (!modest_tny_folder_is_remote_folder (src_folder)) {
3915                 g_object_unref (src_folder);
3916                 return GTK_RESPONSE_OK;
3917         }
3918         g_object_unref (src_folder);
3919
3920         /* now if offline we ask the user */
3921         if(connect_to_get_msg(  GTK_WINDOW (win),
3922                                         tny_list_get_length (headers)))
3923                 response = GTK_RESPONSE_OK;
3924         else
3925                 response = GTK_RESPONSE_CANCEL;
3926
3927         return response;
3928 }
3929
3930
3931
3932 static void
3933 move_to_cb (ModestMailOperation *mail_op, gpointer user_data)
3934 {
3935         MoveToHelper *helper = (MoveToHelper *) user_data;
3936
3937         /* Note that the operation could have failed, in that case do
3938            nothing */
3939         if (modest_mail_operation_get_status (mail_op) == 
3940             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
3941
3942                 GObject *object = modest_mail_operation_get_source (mail_op);
3943                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
3944                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
3945
3946                         if (!modest_msg_view_window_select_next_message (self))
3947                                 if (!modest_msg_view_window_select_previous_message (self))
3948                                         /* No more messages to view, so close this window */
3949                                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3950                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
3951                         GtkWidget *header_view;
3952                         GtkTreePath *path;
3953                         GtkTreeSelection *sel;
3954
3955                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
3956                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3957                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
3958                         path = gtk_tree_row_reference_get_path (helper->reference);
3959                         gtk_tree_selection_select_path (sel, path);
3960                         gtk_tree_path_free (path);
3961                 }
3962                 g_object_unref (object);
3963         }
3964
3965         /* Close the "Pasting" information banner */
3966         gtk_widget_destroy (GTK_WIDGET(helper->banner));
3967         if (helper->reference != NULL)
3968                 gtk_tree_row_reference_free (helper->reference);
3969         g_free (helper);
3970 }
3971
3972 void
3973 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3974                                              gpointer user_data)
3975 {
3976         ModestWindow *main_window = NULL;
3977         GtkWidget *folder_view = NULL;
3978         GObject *win = modest_mail_operation_get_source (mail_op);
3979         const GError *error = NULL;
3980         const gchar *message = NULL;
3981         
3982         /* Get error message */
3983         error = modest_mail_operation_get_error (mail_op);
3984         if (error != NULL && error->message != NULL) {
3985                 message = error->message;
3986         } else {
3987                 message = _("mail_in_ui_folder_move_target_error");
3988         }
3989         
3990         /* Disable next automatic folder selection */
3991         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ());
3992         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
3993                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
3994         modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
3995         
3996         if (user_data && TNY_IS_FOLDER (user_data)) {
3997                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
3998                                                   TNY_FOLDER (user_data), FALSE);
3999         }
4000
4001         /* Show notification dialog */
4002         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
4003         g_object_unref (win);
4004 }
4005
4006 void
4007 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
4008                                               gpointer user_data)
4009 {
4010         GObject *win = modest_mail_operation_get_source (mail_op);
4011         const GError *error = modest_mail_operation_get_error (mail_op);
4012
4013         g_return_if_fail (error != NULL);
4014         if (error->message != NULL)             
4015                 g_printerr ("modest: %s\n", error->message);
4016         else
4017                 g_printerr ("modest: unkonw error on send&receive operation");
4018
4019         /* Show error message */
4020 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
4021 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4022 /*                                                      _CS("sfil_ib_unable_to_receive")); */
4023 /*      else  */
4024 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4025 /*                                                      _CS("sfil_ib_unable_to_send")); */
4026         g_object_unref (win);
4027 }
4028
4029 static void
4030 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4031                        TnyHeader *header, 
4032                        TnyMsg *msg, 
4033                        gpointer user_data)
4034 {
4035         TnyList *parts;
4036         TnyIterator *iter;
4037         gint pending_purges = 0;
4038         gboolean some_purged = FALSE;
4039         ModestWindow *win = MODEST_WINDOW (user_data);
4040         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4041
4042         /* If there was any error */
4043         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4044                 modest_window_mgr_unregister_header (mgr, header);
4045                 return;
4046         }
4047
4048         /* Once the message has been retrieved for purging, we check if
4049          * it's all ok for purging */
4050
4051         parts = tny_simple_list_new ();
4052         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4053         iter = tny_list_create_iterator (parts);
4054
4055         while (!tny_iterator_is_done (iter)) {
4056                 TnyMimePart *part;
4057                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4058                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4059                         if (tny_mime_part_is_purged (part))
4060                                 some_purged = TRUE;
4061                         else
4062                                 pending_purges++;
4063                 }
4064
4065                 if (part)
4066                         g_object_unref (part);
4067
4068                 tny_iterator_next (iter);
4069         }
4070         g_object_unref (iter);
4071         
4072
4073         if (pending_purges>0) {
4074                 gint response;
4075                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4076
4077                 if (response == GTK_RESPONSE_OK) {
4078                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4079                         iter = tny_list_create_iterator (parts);
4080                         while (!tny_iterator_is_done (iter)) {
4081                                 TnyMimePart *part;
4082                                 
4083                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4084                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4085                                         tny_mime_part_set_purged (part);
4086
4087                                 if (part)
4088                                         g_object_unref (part);
4089
4090                                 tny_iterator_next (iter);
4091                         }
4092                         
4093                         tny_msg_rewrite_cache (msg);
4094                 }
4095         } else {
4096                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
4097         }
4098         g_object_unref (iter);
4099
4100         modest_window_mgr_unregister_header (mgr, header);
4101
4102         g_object_unref (parts);
4103 }
4104
4105 static void
4106 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4107                                                      ModestMainWindow *win)
4108 {
4109         GtkWidget *header_view;
4110         TnyList *header_list;
4111         TnyIterator *iter;
4112         TnyHeader *header;
4113         TnyHeaderFlags flags;
4114         ModestWindow *msg_view_window =  NULL;
4115         gboolean found;
4116
4117         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4118
4119         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4120                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4121
4122         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4123
4124         if (tny_list_get_length (header_list) == 1) {
4125                 iter = tny_list_create_iterator (header_list);
4126                 header = TNY_HEADER (tny_iterator_get_current (iter));
4127                 g_object_unref (iter);
4128         } else {
4129                 return;
4130         }
4131
4132         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4133                                                           header, &msg_view_window);
4134         flags = tny_header_get_flags (header);
4135         if (!(flags & TNY_HEADER_FLAG_CACHED))
4136                 return;
4137         if (found) {
4138                 if (msg_view_window != NULL) 
4139                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4140                 else {
4141                         /* do nothing; uid was registered before, so window is probably on it's way */
4142                         g_warning ("debug: header %p has already been registered", header);
4143                 }
4144         } else {
4145                 ModestMailOperation *mail_op = NULL;
4146                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
4147                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4148                                                                          G_OBJECT (win),
4149                                                                          modest_ui_actions_get_msgs_full_error_handler,
4150                                                                          NULL);
4151                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4152                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4153                 
4154                 g_object_unref (mail_op);
4155         }
4156         if (header)
4157                 g_object_unref (header);
4158         if (header_list)
4159                 g_object_unref (header_list);
4160 }
4161
4162 /**
4163  * Utility function that transfer messages from both the main window
4164  * and the msg view window when using the "Move to" dialog
4165  */
4166 static void
4167 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
4168                                               ModestWindow *win)
4169 {
4170         TnyList *headers = NULL;
4171         TnyAccount *dst_account = NULL;
4172         const gchar *proto_str = NULL;
4173         gboolean dst_is_pop = FALSE;
4174
4175         if (!TNY_IS_FOLDER (dst_folder)) {
4176                 modest_platform_information_banner (GTK_WIDGET (win),
4177                                                     NULL,
4178                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
4179                 return;
4180         }
4181
4182         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4183         proto_str = tny_account_get_proto (dst_account);
4184
4185         /* tinymail will return NULL for local folders it seems */
4186         dst_is_pop = proto_str &&
4187                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4188                  MODEST_PROTOCOL_STORE_POP);
4189
4190         g_object_unref (dst_account);
4191
4192         /* Get selected headers */
4193         headers = get_selected_headers (MODEST_WINDOW (win));
4194
4195         if (dst_is_pop) {
4196                 modest_platform_information_banner (GTK_WIDGET (win),
4197                                                     NULL,
4198                                                     ngettext("mail_in_ui_folder_move_target_error",
4199                                                              "mail_in_ui_folder_move_targets_error",
4200                                                              tny_list_get_length (headers)));
4201                 g_object_unref (headers);
4202                 return;
4203         }
4204
4205         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4206         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4207                                                            _CS("ckct_nw_pasting"));
4208         if (helper->banner != NULL)  {
4209                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4210                 gtk_widget_show (GTK_WIDGET(helper->banner));
4211         }
4212
4213         if (MODEST_IS_MAIN_WINDOW (win)) {
4214                 GtkWidget *header_view = 
4215                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4216                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4217                 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4218         }
4219
4220         ModestMailOperation *mail_op = 
4221                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4222                                                                G_OBJECT(win),
4223                                                                modest_ui_actions_move_folder_error_handler,
4224                                                                NULL);
4225         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4226                                          mail_op);
4227
4228         modest_mail_operation_xfer_msgs (mail_op, 
4229                                          headers,
4230                                          TNY_FOLDER (dst_folder),
4231                                          TRUE,
4232                                          move_to_cb,
4233                                          helper);
4234
4235         g_object_unref (G_OBJECT (mail_op));
4236         g_object_unref (headers);
4237 }
4238
4239 /*
4240  * UI handler for the "Move to" action when invoked from the
4241  * ModestMainWindow
4242  */
4243 static void 
4244 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4245                                           GtkWidget *folder_view,
4246                                           TnyFolderStore *dst_folder,
4247                                           ModestMainWindow *win)
4248 {
4249         ModestHeaderView *header_view = NULL;
4250         ModestMailOperation *mail_op = NULL;
4251         TnyFolderStore *src_folder;
4252         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4253
4254         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4255
4256         /* Get the source folder */
4257         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4258
4259         /* Get header view */
4260         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4261
4262         /* Get folder or messages to transfer */
4263         if (gtk_widget_is_focus (folder_view)) {
4264                 GtkTreeSelection *sel;
4265                 gboolean do_xfer = TRUE;
4266
4267                 /* Allow only to transfer folders to the local root folder */
4268                 if (TNY_IS_ACCOUNT (dst_folder) && 
4269                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4270                         do_xfer = FALSE;
4271                 } else if (!TNY_IS_FOLDER (src_folder)) {
4272                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4273                         do_xfer = FALSE;
4274                 } else if (!online && modest_platform_is_network_folderstore(src_folder)) {
4275                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER(src_folder));
4276                         if (!connect_to_get_msg(GTK_WINDOW(win), num_headers)) {
4277                                 do_xfer = FALSE;
4278                         }
4279                 }
4280
4281                 if (do_xfer) {
4282                         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4283                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4284                                                                            _CS("ckct_nw_pasting"));
4285                         if (helper->banner != NULL)  {
4286                                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4287                                 gtk_widget_show (GTK_WIDGET(helper->banner));
4288                         }
4289                         /* Clean folder on header view before moving it */
4290                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4291                         gtk_tree_selection_unselect_all (sel);
4292
4293                         mail_op =
4294                           modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4295                                                                          G_OBJECT(win),
4296                                                                          modest_ui_actions_move_folder_error_handler,
4297                                                                          src_folder);
4298                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4299                                                          mail_op);
4300
4301                         /* Select *after* the changes */
4302                         /* TODO: this function hangs UI after transfer */ 
4303 /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4304 /*                                                        TNY_FOLDER (src_folder), TRUE); */
4305                         
4306                         modest_mail_operation_xfer_folder (mail_op,
4307                                                            TNY_FOLDER (src_folder),
4308                                                            dst_folder,
4309                                                            TRUE, 
4310                                                            move_to_cb, 
4311                                                            helper);
4312                         /* Unref mail operation */
4313                         g_object_unref (G_OBJECT (mail_op));
4314                 }
4315         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4316                 gboolean do_xfer = TRUE;
4317                 /* Ask for confirmation if the source folder is remote and we're not connected */
4318                 if (!online && modest_platform_is_network_folderstore(src_folder)) {
4319                         TnyList *headers = modest_header_view_get_selected_headers(header_view);
4320                         if (!msgs_already_deleted_from_server(headers, src_folder)) {
4321                                 guint num_headers = tny_list_get_length(headers);
4322                                 if (!connect_to_get_msg(GTK_WINDOW(win), num_headers)) {
4323                                         do_xfer = FALSE;
4324                                 }
4325                         }
4326                         g_object_unref(headers);
4327                 }
4328                 if (do_xfer) /* Transfer messages */
4329                         modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4330         }
4331
4332     if (src_folder)
4333         g_object_unref (src_folder);
4334 }
4335
4336
4337 /*
4338  * UI handler for the "Move to" action when invoked from the
4339  * ModestMsgViewWindow
4340  */
4341 static void 
4342 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4343                                               TnyFolderStore *dst_folder,
4344                                               ModestMsgViewWindow *win)
4345 {
4346         TnyHeader *header = NULL;
4347         TnyFolderStore *src_folder;
4348
4349         /* Create header list */
4350         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4351         src_folder = TNY_FOLDER_STORE(tny_header_get_folder(header));
4352         g_object_unref (header);
4353
4354         /* Transfer the message if online or confirmed by the user */
4355         if (tny_device_is_online (modest_runtime_get_device()) || remote_folder_is_pop(src_folder) ||
4356             (modest_platform_is_network_folderstore(src_folder) && connect_to_get_msg(GTK_WINDOW(win), 1))) {
4357                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4358         }
4359
4360         g_object_unref (src_folder);
4361 }
4362
4363 void 
4364 modest_ui_actions_on_move_to (GtkAction *action, 
4365                               ModestWindow *win)
4366 {
4367         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4368         gint result = 0;
4369         TnyFolderStore *dst_folder = NULL;
4370         ModestMainWindow *main_window;
4371
4372         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4373                           MODEST_IS_MSG_VIEW_WINDOW (win));
4374
4375         /* Get the main window if exists */
4376         if (MODEST_IS_MAIN_WINDOW (win))
4377                 main_window = MODEST_MAIN_WINDOW (win);
4378         else
4379                 main_window = 
4380                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
4381
4382         /* Get the folder view widget if exists */
4383         if (main_window)
4384                 folder_view = modest_main_window_get_child_widget (main_window,
4385                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4386         else
4387                 folder_view = NULL;
4388
4389         /* Create and run the dialog */
4390         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4391         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4392         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4393         result = gtk_dialog_run (GTK_DIALOG(dialog));
4394         g_object_ref (tree_view);
4395         gtk_widget_destroy (dialog);
4396
4397         if (result != GTK_RESPONSE_ACCEPT)
4398                 return;
4399
4400         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4401         /* Do window specific stuff */
4402         if (MODEST_IS_MAIN_WINDOW (win)) {
4403                 modest_ui_actions_on_main_window_move_to (action,
4404                                                           folder_view,
4405                                                           dst_folder,
4406                                                           MODEST_MAIN_WINDOW (win));
4407         } else {
4408                 modest_ui_actions_on_msg_view_window_move_to (action,
4409                                                               dst_folder,
4410                                                               MODEST_MSG_VIEW_WINDOW (win));
4411         }
4412
4413         if (dst_folder)
4414                 g_object_unref (dst_folder);
4415 }
4416
4417 /*
4418  * Calls #HeadersFunc for each header already selected in the main
4419  * window or the message currently being shown in the msg view window
4420  */
4421 static void
4422 do_headers_action (ModestWindow *win, 
4423                    HeadersFunc func,
4424                    gpointer user_data)
4425 {
4426         TnyList *headers_list = NULL;
4427         TnyIterator *iter = NULL;
4428         TnyHeader *header = NULL;
4429         TnyFolder *folder = NULL;
4430
4431         /* Get headers */
4432         headers_list = get_selected_headers (win);
4433         if (!headers_list)
4434                 return;
4435
4436         /* Get the folder */
4437         iter = tny_list_create_iterator (headers_list);
4438         header = TNY_HEADER (tny_iterator_get_current (iter));
4439         if (header) {
4440                 folder = tny_header_get_folder (header);
4441                 g_object_unref (header);
4442         }
4443
4444         /* Call the function for each header */
4445         while (!tny_iterator_is_done (iter)) {
4446                 header = TNY_HEADER (tny_iterator_get_current (iter));
4447                 func (header, win, user_data);
4448                 g_object_unref (header);
4449                 tny_iterator_next (iter);
4450         }
4451
4452         /* Trick: do a poke status in order to speed up the signaling
4453            of observers */
4454         tny_folder_poke_status (folder);
4455
4456         /* Frees */
4457         g_object_unref (folder);
4458         g_object_unref (iter);
4459         g_object_unref (headers_list);
4460 }
4461
4462 void 
4463 modest_ui_actions_view_attachment (GtkAction *action,
4464                                    ModestWindow *window)
4465 {
4466         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4467                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4468         } else {
4469                 /* not supported window for this action */
4470                 g_return_if_reached ();
4471         }
4472 }
4473
4474 void
4475 modest_ui_actions_save_attachments (GtkAction *action,
4476                                     ModestWindow *window)
4477 {
4478         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4479                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4480         } else {
4481                 /* not supported window for this action */
4482                 g_return_if_reached ();
4483         }
4484 }
4485
4486 void
4487 modest_ui_actions_remove_attachments (GtkAction *action,
4488                                       ModestWindow *window)
4489 {
4490         if (MODEST_IS_MAIN_WINDOW (window)) {
4491                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4492         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4493                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4494         } else {
4495                 /* not supported window for this action */
4496                 g_return_if_reached ();
4497         }
4498 }
4499
4500 void 
4501 modest_ui_actions_on_settings (GtkAction *action, 
4502                                ModestWindow *win)
4503 {
4504         GtkWidget *dialog;
4505
4506         dialog = modest_platform_get_global_settings_dialog ();
4507         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4508         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4509         gtk_widget_show_all (dialog);
4510
4511         gtk_dialog_run (GTK_DIALOG (dialog));
4512
4513         gtk_widget_destroy (dialog);
4514 }
4515
4516 void 
4517 modest_ui_actions_on_help (GtkAction *action, 
4518                            ModestWindow *win)
4519 {
4520         const gchar *help_id = NULL;
4521
4522         if (MODEST_IS_MAIN_WINDOW (win)) {
4523                 GtkWidget *folder_view;
4524                 TnyFolderStore *folder_store;
4525                 
4526                 /* Get selected folder */
4527                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4528                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4529                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4530
4531                 /* Switch help_id */
4532                 if (TNY_IS_FOLDER (folder_store)) {
4533                         switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
4534                         case TNY_FOLDER_TYPE_NORMAL:
4535                                 help_id = "applications_email_managefolders";
4536                                 break;
4537                         case TNY_FOLDER_TYPE_INBOX:
4538                                 help_id = "applications_email_inbox";
4539                                 break;
4540                         case TNY_FOLDER_TYPE_OUTBOX:
4541                                 help_id = "applications_email_outbox";
4542                                 break;
4543                         case TNY_FOLDER_TYPE_SENT:
4544                                 help_id = "applications_email_sent";
4545                                 break;
4546                         case TNY_FOLDER_TYPE_DRAFTS:
4547                                 help_id = "applications_email_drafts";
4548                                 break;
4549                         case TNY_FOLDER_TYPE_ARCHIVE:
4550                                 help_id = "applications_email_managefolders";
4551                                 break;
4552                         default:
4553                                 help_id = "applications_email_managefolders";
4554                         }
4555                 } else {
4556                         help_id = "applications_email_mainview";
4557                 }
4558                 g_object_unref (folder_store);
4559         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4560                 help_id = "applications_email_viewer";
4561         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
4562                 help_id = "applications_email_editor";
4563
4564         modest_platform_show_help (GTK_WINDOW (win), help_id);
4565 }
4566
4567 void 
4568 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4569                                             ModestWindow *window)
4570 {
4571         ModestMailOperation *mail_op;
4572         TnyList *headers;
4573
4574         /* Get headers */
4575         headers = get_selected_headers (window);
4576         if (!headers)
4577                 return;
4578
4579         /* Create mail operation */
4580         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4581                                                                  G_OBJECT (window),
4582                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4583                                                                  NULL);
4584         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4585         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4586
4587         /* Frees */
4588         g_object_unref (headers);
4589         g_object_unref (mail_op);
4590 }
4591
4592 void
4593 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4594                                           ModestWindow *window)
4595 {
4596         g_return_if_fail (MODEST_IS_WINDOW (window));
4597         
4598         /* Update dimmed */     
4599         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4600 }
4601
4602 void
4603 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4604                                           ModestWindow *window)
4605 {
4606         g_return_if_fail (MODEST_IS_WINDOW (window));
4607
4608         /* Update dimmed */     
4609         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4610 }
4611
4612 void
4613 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4614                                           ModestWindow *window)
4615 {
4616         g_return_if_fail (MODEST_IS_WINDOW (window));
4617
4618         /* Update dimmed */     
4619         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4620 }
4621
4622 void
4623 modest_ui_actions_on_format_menu_activated (GtkAction *action,
4624                                             ModestWindow *window)
4625 {
4626         g_return_if_fail (MODEST_IS_WINDOW (window));
4627
4628         /* Update dimmed */     
4629         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4630 }
4631
4632 void
4633 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4634                                           ModestWindow *window)
4635 {
4636         g_return_if_fail (MODEST_IS_WINDOW (window));
4637
4638         /* Update dimmed */     
4639         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4640 }
4641
4642 void
4643 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4644                                           ModestWindow *window)
4645 {
4646         g_return_if_fail (MODEST_IS_WINDOW (window));
4647
4648         /* Update dimmed */     
4649         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4650 }
4651
4652 void
4653 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4654                                                  ModestWindow *window)
4655 {
4656         g_return_if_fail (MODEST_IS_WINDOW (window));
4657
4658         /* Update dimmed */     
4659         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4660 }
4661
4662 void
4663 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4664                                                      ModestWindow *window)
4665 {
4666         g_return_if_fail (MODEST_IS_WINDOW (window));
4667
4668         /* Update dimmed */     
4669         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4670 }
4671
4672 void
4673 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4674                                                      ModestWindow *window)
4675 {
4676         g_return_if_fail (MODEST_IS_WINDOW (window));
4677
4678         /* Update dimmed */     
4679         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4680 }
4681
4682 void
4683 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4684 {
4685         g_return_if_fail (MODEST_IS_WINDOW (window));
4686
4687         /* Update dimmed */     
4688         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4689 }
4690
4691 void
4692 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4693 {
4694         g_return_if_fail (MODEST_IS_WINDOW (window));
4695
4696         modest_platform_show_search_messages (GTK_WINDOW (window));
4697 }
4698
4699 void     
4700 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4701 {
4702         g_return_if_fail (MODEST_IS_WINDOW (win));
4703         modest_platform_show_addressbook (GTK_WINDOW (win));
4704 }
4705
4706
4707 void
4708 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4709                                           ModestWindow *window)
4710 {
4711         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4712
4713         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4714 }
4715
4716 static void 
4717 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
4718                                    ModestMailOperationState *state,
4719                                    gpointer user_data)
4720 {
4721         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
4722
4723         /* Set send/receive operation finished */       
4724         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
4725                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
4726         
4727 }
4728
4729
4730 void 
4731 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
4732                                                 TnyHeader *header, 
4733                                                 TnyMsg *msg, 
4734                                                 GError *err, 
4735                                                 gpointer user_data)
4736 {
4737         const gchar* server_name = NULL;
4738         TnyTransportAccount *server_account;
4739         gchar *message = NULL;
4740
4741         /* Don't show anything if the user cancelled something */
4742         if (err->code == TNY_TRANSPORT_ACCOUNT_ERROR_SEND_USER_CANCEL)
4743                 return;
4744
4745         /* Get the server name: */
4746         server_account = 
4747                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
4748         if (server_account) {
4749                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
4750                         
4751                 g_object_unref (server_account);
4752                 server_account = NULL;
4753         }
4754         
4755         g_return_if_fail (server_name);
4756
4757         /* Show the appropriate message text for the GError: */
4758         switch (err->code) {
4759         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
4760                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4761                 break;
4762         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
4763                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4764                 break;
4765         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
4766                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
4767                 break;
4768         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
4769                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
4770                 break;
4771         default:
4772                 g_return_if_reached ();
4773         }
4774         
4775         /* TODO if the username or the password where not defined we
4776            should show the Accounts Settings dialog or the Connection
4777            specific SMTP server window */
4778
4779         modest_platform_run_information_dialog (NULL, message);
4780         g_free (message);
4781 }
4782
4783 void
4784 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
4785                                                 gchar *msg_id, 
4786                                                 guint status,
4787                                                 gpointer user_data)
4788 {
4789         ModestMainWindow *main_window = NULL;
4790         ModestWindowMgr *mgr = NULL;
4791         GtkWidget *folder_view = NULL, *header_view = NULL;
4792         TnyFolderStore *selected_folder = NULL;
4793         TnyFolderType folder_type;
4794
4795         mgr = modest_runtime_get_window_mgr ();
4796         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr));
4797
4798         if (!main_window)
4799                 return;
4800
4801         /* Check if selected folder is OUTBOX */
4802         folder_view = modest_main_window_get_child_widget (main_window,
4803                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4804         header_view = modest_main_window_get_child_widget (main_window,
4805                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4806
4807         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4808         if (!TNY_IS_FOLDER (selected_folder)) 
4809                 goto frees;
4810
4811         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
4812 #if GTK_CHECK_VERSION(2, 8, 0) 
4813         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
4814         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
4815                 GtkTreeViewColumn *tree_column;
4816
4817                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
4818                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
4819                 gtk_tree_view_column_queue_resize (tree_column);
4820         }
4821 #else
4822         gtk_widget_queue_draw (header_view);
4823 #endif          
4824         
4825         /* Free */
4826  frees:
4827         if (selected_folder != NULL)
4828                 g_object_unref (selected_folder);
4829 }