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