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