* Implement optimizations on DimmingRules management.
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29  
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <glib/gprintf.h>
36 #include <string.h>
37 #include <modest-runtime.h>
38 #include <modest-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
44
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include <tny-mime-part.h>
48 #include <tny-camel-folder.h>
49 #include <tny-camel-imap-folder.h>
50 #include <tny-camel-pop-folder.h>
51
52 #ifdef MODEST_PLATFORM_MAEMO
53 #include "maemo/modest-osso-state-saving.h"
54 #include "maemo/modest-maemo-utils.h"
55 #include "maemo/modest-hildon-includes.h"
56 #endif /* MODEST_PLATFORM_MAEMO */
57
58 #include "widgets/modest-ui-constants.h"
59 #include <widgets/modest-main-window.h>
60 #include <widgets/modest-msg-view-window.h>
61 #include <widgets/modest-account-view-window.h>
62 #include <widgets/modest-details-dialog.h>
63 #include <widgets/modest-attachments-view.h>
64 #include "widgets/modest-folder-view.h"
65 #include "widgets/modest-global-settings-dialog.h"
66 #include "modest-connection-specific-smtp-window.h"
67 #include "modest-account-mgr-helpers.h"
68 #include "modest-mail-operation.h"
69 #include "modest-text-utils.h"
70
71 #ifdef MODEST_HAVE_EASYSETUP
72 #include "easysetup/modest-easysetup-wizard.h"
73 #endif /* MODEST_HAVE_EASYSETUP */
74
75 #include <modest-widget-memory.h>
76 #include <tny-error.h>
77 #include <tny-simple-list.h>
78 #include <tny-msg-view.h>
79 #include <tny-device.h>
80 #include <tny-merge-folder.h>
81
82 #include <gtkhtml/gtkhtml.h>
83
84 typedef struct _GetMsgAsyncHelper {     
85         ModestWindow *window;
86         ModestMailOperation *mail_op;
87         TnyIterator *iter;
88         guint num_ops;
89         GFunc func;     
90         gpointer user_data;
91 } GetMsgAsyncHelper;
92
93 typedef enum _ReplyForwardAction {
94         ACTION_REPLY,
95         ACTION_REPLY_TO_ALL,
96         ACTION_FORWARD
97 } ReplyForwardAction;
98
99 typedef struct _ReplyForwardHelper {
100         guint reply_forward_type;
101         ReplyForwardAction action;
102         gchar *account_name;
103         GtkWidget *parent_window;
104 } ReplyForwardHelper;
105
106 typedef struct _PasteAsAttachmentHelper {
107         ModestMsgEditWindow *window;
108         GtkWidget *banner;
109 } PasteAsAttachmentHelper;
110
111
112 /*
113  * The do_headers_action uses this kind of functions to perform some
114  * action to each member of a list of headers
115  */
116 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
117
118 static void     do_headers_action     (ModestWindow *win, 
119                                        HeadersFunc func,
120                                        gpointer user_data);
121
122 static void     open_msg_cb            (ModestMailOperation *mail_op, 
123                                         TnyHeader *header, 
124                                         TnyMsg *msg,
125                                         gpointer user_data);
126
127 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
128                                         TnyHeader *header, 
129                                         TnyMsg *msg,
130                                         gpointer user_data);
131
132 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
133
134 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
135                                         TnyFolder *folder, 
136                                         gpointer user_data);
137
138 static void     _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
139                                                    ModestMailOperationState *state,
140                                                    gpointer user_data);
141
142 static gboolean
143 download_uncached_messages (TnyList *header_list, GtkWindow *win,
144                             gboolean reply_fwd);
145
146
147 static void
148 run_account_setup_wizard (ModestWindow *win)
149 {
150         ModestEasysetupWizardDialog *wizard;
151         
152         g_return_if_fail (MODEST_IS_WINDOW(win));
153         
154         wizard = modest_easysetup_wizard_dialog_new ();
155         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
156         
157         /* Don't make this a modal window, because secondary windows will then 
158          * be unusable, freezing the UI: */
159         /* gtk_window_set_modal (GTK_WINDOW (wizard), TRUE); */
160         
161         gtk_dialog_run (GTK_DIALOG (wizard));
162         gtk_widget_destroy (GTK_WIDGET (wizard));
163 }
164
165
166 void   
167 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
168 {
169         GtkWidget *about;
170         const gchar *authors[] = {
171                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
172                 NULL
173         };
174         about = gtk_about_dialog_new ();
175         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
176         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
177         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
178                                         _("Copyright (c) 2006, Nokia Corporation\n"
179                                           "All rights reserved."));
180         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
181                                        _("a modest e-mail client\n\n"
182                                          "design and implementation: Dirk-Jan C. Binnema\n"
183                                          "contributions from the fine people at KC and Ig\n"
184                                          "uses the tinymail email framework written by Philip van Hoof"));
185         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
186         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
187         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
188         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
189         
190         gtk_dialog_run (GTK_DIALOG (about));
191         gtk_widget_destroy(about);
192 }
193
194 /*
195  * Gets the list of currently selected messages. If the win is the
196  * main window, then it returns a newly allocated list of the headers
197  * selected in the header view. If win is the msg view window, then
198  * the value returned is a list with just a single header.
199  *
200  * The caller of this funcion must free the list.
201  */
202 static TnyList *
203 get_selected_headers (ModestWindow *win)
204 {
205         if (MODEST_IS_MAIN_WINDOW(win)) {
206                 GtkWidget *header_view;         
207                 
208                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
209                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
210                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
211                 
212         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
213                 /* for MsgViewWindows, we simply return a list with one element */
214                 TnyHeader *header;
215                 TnyList *list = NULL;
216                 
217                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
218                 if (header != NULL) {
219                         list = tny_simple_list_new ();
220                         tny_list_prepend (list, G_OBJECT(header));
221                         g_object_unref (G_OBJECT(header));
222                 }
223
224                 return list;
225
226         } else
227                 return NULL;
228 }
229
230 static void
231 headers_action_mark_as_read (TnyHeader *header,
232                              ModestWindow *win,
233                              gpointer user_data)
234 {
235         TnyHeaderFlags flags;
236
237         g_return_if_fail (TNY_IS_HEADER(header));
238
239         flags = tny_header_get_flags (header);
240         if (flags & TNY_HEADER_FLAG_SEEN) return;
241         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
242 }
243
244 static void
245 headers_action_mark_as_unread (TnyHeader *header,
246                                ModestWindow *win,
247                                gpointer user_data)
248 {
249         TnyHeaderFlags flags;
250
251         g_return_if_fail (TNY_IS_HEADER(header));
252
253         flags = tny_header_get_flags (header);
254         if (flags & TNY_HEADER_FLAG_SEEN)  {
255                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
256         }
257 }
258
259 /** A convenience method, because deleting a message is 
260  * otherwise complicated, and it's best to change it in one place 
261  * when we change it.
262  */
263 void modest_do_message_delete (TnyHeader *header, ModestWindow *win)
264 {
265         ModestMailOperation *mail_op = NULL;
266         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, 
267                 win ? G_OBJECT(win) : NULL);
268         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
269                                          mail_op);
270         
271         /* Always delete. TODO: Move to trash still not supported */
272         modest_mail_operation_remove_msg (mail_op, header, FALSE);
273         g_object_unref (G_OBJECT (mail_op));
274 }
275
276 static void
277 headers_action_delete (TnyHeader *header,
278                        ModestWindow *win,
279                        gpointer user_data)
280 {
281         modest_do_message_delete (header, win);
282 }
283
284 /** After deleing a message that is currently visible in a window, 
285  * show the next message from the list, or close the window if there are no more messages.
286  **/
287 void modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
288 {
289         /* Close msg view window or select next */
290         if (modest_msg_view_window_last_message_selected (win) &&
291                 modest_msg_view_window_first_message_selected (win)) {
292                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
293         } else {
294                 if (!modest_msg_view_window_select_next_message (win)) {
295                         gboolean ret_value;
296                         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
297                 }
298         }
299 }
300
301 void
302 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
303 {
304         TnyList *header_list = NULL;
305         TnyIterator *iter = NULL;
306         TnyHeader *header = NULL;
307         gchar *message = NULL;
308         gchar *desc = NULL;
309         gint response;
310         ModestWindowMgr *mgr;
311         GtkWidget *header_view = NULL;
312
313         g_return_if_fail (MODEST_IS_WINDOW(win));
314         
315         /* Check first if the header view has the focus */
316         if (MODEST_IS_MAIN_WINDOW (win)) {
317                 header_view = 
318                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
319                                                              MODEST_WIDGET_TYPE_HEADER_VIEW);
320                 if (!gtk_widget_is_focus (header_view))
321                         return;
322         }
323         
324         /* Get the headers, either from the header view (if win is the main window),
325          * or from the message view window: */
326         header_list = get_selected_headers (win);
327         if (!header_list) return;
328                         
329         /* Check if any of the headers are already opened, or in the process of being opened */
330         if (MODEST_IS_MAIN_WINDOW (win)) {
331                 gboolean found;
332                 iter = tny_list_create_iterator (header_list);
333                 found = FALSE;
334                 mgr = modest_runtime_get_window_mgr ();
335                 while (!tny_iterator_is_done (iter) && !found) {
336                         header = TNY_HEADER (tny_iterator_get_current (iter));
337                         if (header) {
338                                 found =  modest_window_mgr_find_registered_header (mgr, header, NULL);
339                                 g_object_unref (header);
340                         }
341
342                         tny_iterator_next (iter);
343                 }
344                 g_object_unref (iter);
345
346                 if (found) {
347                         gchar *num, *msg;
348
349                         num = g_strdup_printf ("%d", tny_list_get_length (header_list));
350                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), num);
351
352                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
353                         
354                         g_free (msg);
355                         g_free (num);
356                         g_object_unref (header_list);
357                         return;
358                 }
359         }
360
361         /* Select message */
362         if (tny_list_get_length(header_list) == 1) {
363                 iter = tny_list_create_iterator (header_list);
364                 header = TNY_HEADER (tny_iterator_get_current (iter));
365                 if (header) {
366                         desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
367                         g_object_unref (header);
368                 }
369
370                 g_object_unref (iter);
371         }
372         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
373                                            tny_list_get_length(header_list)), desc);
374
375         /* Confirmation dialog */
376         printf("DEBUG: %s\n", __FUNCTION__);    
377         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
378                                                             message);
379         
380
381         if (response == GTK_RESPONSE_OK) {      
382                 ModestWindow *main_window = NULL;
383                 ModestWindowMgr *mgr = NULL;
384                 GtkTreeModel *model = NULL;
385                 GtkTreeSelection *sel = NULL;
386                 GList *sel_list = NULL, *tmp = NULL;
387                 GtkTreeRowReference *row_reference = NULL;
388                 GtkTreePath *next_path = NULL;
389                 TnyFolder *folder = NULL;
390                 GError *err = NULL;
391
392                 /* Find last selected row */                    
393                 if (MODEST_IS_MAIN_WINDOW (win)) {
394                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
395                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
396                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
397                         for (tmp=sel_list; tmp; tmp=tmp->next) {
398                                 if (tmp->next == NULL) {
399                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
400                                         gtk_tree_path_next (next_path);
401                                         row_reference = gtk_tree_row_reference_new (model, next_path);
402                                         gtk_tree_path_free (next_path);
403                                 }
404                         }
405                 }
406                 
407                 /* Remove each header. If it's a view window header_view == NULL */
408                 do_headers_action (win, headers_action_delete, header_view);
409
410                 /* refresh the header view (removing marked-as-deleted)*/
411                 modest_header_view_refilter (MODEST_HEADER_VIEW(header_view)); 
412                 
413                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
414                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
415                         
416                         /* Get main window */
417                         mgr = modest_runtime_get_window_mgr ();
418                         main_window = modest_window_mgr_get_main_window (mgr);
419                 }
420                 else {                  
421                         /* Move cursor to next row */
422                         main_window = win; 
423
424                         /* Select next row */
425                         if (gtk_tree_row_reference_valid (row_reference)) {
426                                 next_path = gtk_tree_row_reference_get_path (row_reference);
427                                 gtk_tree_selection_select_path (sel, next_path);
428                                 gtk_tree_path_free (next_path);
429                         }
430                         if (row_reference != NULL)
431                                 gtk_tree_row_reference_free (row_reference);
432                 }
433
434                 /* Get folder from first header and sync it */
435                 iter = tny_list_create_iterator (header_list);
436                 header = TNY_HEADER (tny_iterator_get_current (iter));
437                 folder = tny_header_get_folder (header);
438                 if (TNY_IS_CAMEL_IMAP_FOLDER (folder))
439 /*                      tny_folder_sync_async(folder, FALSE, NULL, NULL, NULL); /\* FALSE --> don't expunge *\/ */
440                         tny_folder_sync (folder, FALSE, &err); /* FALSE --> don't expunge */
441 /*              else if (TNY_IS_CAMEL_POP_FOLDER (folder)) */
442 /*                      tny_folder_sync_async(folder, FALSE, NULL, NULL, NULL); /\* TRUE --> dont expunge *\/ */
443 /*                      tny_folder_sync (folder, TRUE, &err); /\* TRUE --> expunge *\/ */
444                 else
445                         /* local folders */
446 /*                      tny_folder_sync_async(folder, TRUE, NULL, NULL, NULL); /\* TRUE --> expunge *\/ */
447                         tny_folder_sync (folder, TRUE, &err); /* TRUE --> expunge */
448
449                 if (err != NULL) {
450                         printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, err->code, err->message);
451                         g_error_free(err);
452                 }
453
454                 g_object_unref (header);
455                 g_object_unref (iter);
456                 g_object_unref (folder);
457                 
458                 /* Update toolbar dimming state */
459                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
460
461                 /* Free */
462                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
463                 g_list_free (sel_list);
464         }
465
466         /* Free*/
467         g_free(message);
468         g_free(desc);
469         g_object_unref (header_list);
470 }
471
472
473
474
475 /* delete either message or folder, based on where we are */
476 void
477 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
478 {
479         g_return_if_fail (MODEST_IS_WINDOW(win));
480         
481         /* Check first if the header view has the focus */
482         if (MODEST_IS_MAIN_WINDOW (win)) {
483                 GtkWidget *w;
484                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
485                                                          MODEST_WIDGET_TYPE_FOLDER_VIEW);
486                 if (gtk_widget_is_focus (w)) {
487                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
488                         return;
489                 }
490         }
491         modest_ui_actions_on_delete_message (action, win);
492 }
493
494
495
496 void
497 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
498 {
499 #ifdef MODEST_PLATFORM_MAEMO
500         modest_osso_save_state();
501 #endif /* MODEST_PLATFORM_MAEMO */
502
503         g_debug ("closing down, clearing %d item(s) from operation queue",
504                  modest_mail_operation_queue_num_elements
505                  (modest_runtime_get_mail_operation_queue()));
506
507         /* cancel all outstanding operations */
508         modest_mail_operation_queue_cancel_all 
509                 (modest_runtime_get_mail_operation_queue());
510         
511         g_debug ("queue has been cleared");
512
513         /* note: when modest-tny-account-store is finalized,
514            it will automatically set all network connections
515            to offline */
516
517         gtk_main_quit ();
518 }
519
520 void
521 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
522 {
523         gboolean ret_value;
524
525         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
526
527 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
528 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
529 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
530 /*              gboolean ret_value; */
531 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
532 /*      } else if (MODEST_IS_WINDOW (win)) { */
533 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
534 /*      } else { */
535 /*              g_return_if_reached (); */
536 /*      } */
537 }
538
539 void
540 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
541 {
542         GtkClipboard *clipboard = NULL;
543         gchar *selection = NULL;
544
545         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
546         selection = gtk_clipboard_wait_for_text (clipboard);
547
548         /* Question: why is the clipboard being used here? 
549          * It doesn't really make a lot of sense. */
550
551         if (selection)
552         {
553                 modest_address_book_add_address (selection);
554                 g_free (selection);
555         }
556 }
557
558 void
559 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
560 {
561         /* This is currently only implemented for Maemo */
562 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
563         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
564                 run_account_setup_wizard (win);
565                 return;
566         } else  {
567                 /* Show the list of accounts: */
568                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
569                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW (win));
570                 
571                 /* Don't make this a modal window, because secondary windows will then 
572                  * be unusable, freezing the UI: */
573                 /* gtk_window_set_modal (GTK_WINDOW (account_win), TRUE); */
574                 modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), account_win); 
575         }
576 #else
577         GtkWidget *dialog, *label;
578         
579         /* Create the widgets */
580         
581         dialog = gtk_dialog_new_with_buttons ("Message",
582                                               GTK_WINDOW(win),
583                                               GTK_DIALOG_DESTROY_WITH_PARENT,
584                                               GTK_STOCK_OK,
585                                               GTK_RESPONSE_NONE,
586                                               NULL);
587         label = gtk_label_new ("Hello World!");
588         
589         /* Ensure that the dialog box is destroyed when the user responds. */
590         
591         g_signal_connect_swapped (dialog, "response", 
592                                   G_CALLBACK (gtk_widget_destroy),
593                                   dialog);
594         
595         /* Add the label, and show everything we've added to the dialog. */
596         
597         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
598                            label);
599         gtk_widget_show_all (dialog);
600 #endif /* MODEST_PLATFORM_MAEMO */
601 }
602
603 static void
604 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
605 {
606         ModestWindow *main_window = MODEST_WINDOW (user_data);
607         
608         /* Save any changes. */
609         modest_connection_specific_smtp_window_save_server_accounts (
610                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window), 
611                         modest_window_get_active_account (main_window));
612         gtk_widget_destroy (GTK_WIDGET (window));
613 }
614
615
616
617 void
618 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
619 {
620         /* This is currently only implemented for Maemo,
621          * because it requires an API (libconic) to detect different connection 
622          * possiblities.
623          */
624 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
625         
626         /* Create the window if necessary: */
627         const gchar *active_account_name = modest_window_get_active_account (win);
628         
629         /* TODO: Dim the menu item (not in the UI spec)? or show a warning,
630          * or show the default account?
631          * If we show the default account then the account name should be shown in 
632          * the window when we show it. */
633         if (!active_account_name) {
634                 g_warning ("%s: No account is active.", __FUNCTION__);
635                 return;
636         }
637                 
638         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
639         modest_connection_specific_smtp_window_fill_with_connections (
640                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
641                 modest_runtime_get_account_mgr(), 
642                 active_account_name);
643
644         /* Show the window: */  
645         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
646         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
647         gtk_widget_show (specific_window);
648     
649         /* Save changes when the window is hidden: */
650         g_signal_connect (specific_window, "hide", 
651                 G_CALLBACK (on_smtp_servers_window_hide), win);
652 #endif /* MODEST_PLATFORM_MAEMO */
653 }
654
655 void
656 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
657 {
658         ModestWindow *msg_win = NULL;
659         TnyMsg *msg = NULL;
660         TnyFolder *folder = NULL;
661         gchar *account_name = NULL;
662         gchar *from_str = NULL;
663 /*      GError *err = NULL; */
664         TnyAccount *account = NULL;
665         ModestWindowMgr *mgr;
666         gchar *signature = NULL, *blank_and_signature = NULL;
667
668         /* if there are no accounts yet, just show the wizard */
669         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
670                         run_account_setup_wizard (win);
671                         return;
672         }
673         
674         account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
675         if (!account_name)
676                 account_name = g_strdup (modest_window_get_active_account (win));
677         if (!account_name) {
678                 g_printerr ("modest: no account found\n");
679                 goto cleanup;
680         }
681         
682         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
683                                                                        account_name,
684                                                                        TNY_ACCOUNT_TYPE_STORE);
685         if (!account) {
686                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
687                 goto cleanup;
688         }
689
690         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
691         if (!from_str) {
692                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
693                 goto cleanup;
694         }
695
696         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr (), account_name,
697                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
698                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), account_name,
699                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
700                 blank_and_signature = g_strconcat ("\n", signature, NULL);
701                 g_free (signature);
702         } else {
703                 blank_and_signature = g_strdup ("");
704         }
705
706         msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
707         if (!msg) {
708                 g_printerr ("modest: failed to create new msg\n");
709                 goto cleanup;
710         }
711         
712         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
713         if (!folder) {
714                 g_printerr ("modest: failed to find Drafts folder\n");
715                 goto cleanup;
716         }
717         
718
719         /* Create and register edit window */
720         /* This is destroyed by TOOD. */
721         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
722         mgr = modest_runtime_get_window_mgr ();
723         modest_window_mgr_register_window (mgr, msg_win);
724
725         if (win)
726                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
727                                               GTK_WINDOW (win));        
728         gtk_widget_show_all (GTK_WIDGET (msg_win));
729
730 cleanup:
731         g_free (account_name);
732         g_free (from_str);
733         g_free (blank_and_signature);
734         if (msg_win)
735                 g_object_unref (msg_win);
736         if (account)
737                 g_object_unref (G_OBJECT(account));
738         if (msg)
739                 g_object_unref (G_OBJECT(msg));
740         if (folder)
741                 g_object_unref (G_OBJECT(folder));
742 }
743
744 gboolean 
745 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
746                                        TnyHeader *header,
747                                        TnyMsg *msg)
748 {
749         ModestMailOperationStatus status;
750
751         /* If there is no message or the operation was not successful */
752         status = modest_mail_operation_get_status (mail_op);
753         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
754
755                 /* Remove the header from the preregistered uids */
756                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
757                                                      header);
758
759                 return FALSE;
760         }
761
762         return TRUE;
763 }
764
765 static void
766 open_msg_cb (ModestMailOperation *mail_op, 
767              TnyHeader *header, 
768              TnyMsg *msg, 
769              gpointer user_data)
770 {
771         ModestWindowMgr *mgr = NULL;
772         ModestWindow *parent_win = NULL;
773         ModestWindow *win = NULL;
774         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
775         gchar *account = NULL;
776         TnyFolder *folder;
777         
778         /* Do nothing if there was any problem with the mail
779            operation. The error will be shown by the error_handler of
780            the mail operation */
781         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
782                 return;
783         }
784
785         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
786         folder = tny_header_get_folder (header);
787
788         /* Mark header as read */
789         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
790
791         /* Get account */
792         account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
793         if (!account)
794                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
795         
796         /* Gets folder type (OUTBOX headers will be opened in edit window */
797         if (modest_tny_folder_is_local_folder (folder))
798                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
799
800         /* If the header is in the drafts folder then open the editor,
801            else the message view window */
802         if ((folder_type == TNY_FOLDER_TYPE_DRAFTS) ||
803             (folder_type == TNY_FOLDER_TYPE_OUTBOX)) {
804                 /* we cannot edit without a valid account... */
805                 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
806                         run_account_setup_wizard(parent_win);
807                         goto cleanup;
808                 }
809                 win = modest_msg_edit_window_new (msg, account, TRUE);
810                 
811         } else {
812                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
813                 
814                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
815                         GtkWidget *header_view;
816                         GtkTreeSelection *sel;
817                         GList *sel_list = NULL;
818                         GtkTreeModel *model;
819                         
820                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
821                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
822
823                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
824                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
825
826                         if (sel_list != NULL) {
827                                 GtkTreeRowReference *row_reference;
828
829                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
830                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
831                                 g_list_free (sel_list);
832                                 
833                                 win = modest_msg_view_window_new_with_header_model (msg, 
834                                                                                     account,
835                                                                                     (const gchar*) uid,
836                                                                                     model, 
837                                                                                     row_reference);
838                                 gtk_tree_row_reference_free (row_reference);
839                         } else {
840                                 win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
841                         }
842                 } else {
843                         win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
844                 }
845                 g_free (uid);
846         }
847         
848         /* Register and show new window */
849         if (win != NULL) {
850                 mgr = modest_runtime_get_window_mgr ();
851                 modest_window_mgr_register_window (mgr, win);
852                 g_object_unref (win);
853                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
854                 gtk_widget_show_all (GTK_WIDGET(win));
855         }
856
857         /* Update toolbar dimming state */
858         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
859                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
860         }
861
862 cleanup:
863         /* Free */
864         g_free(account);
865         g_object_unref (parent_win);
866         g_object_unref (folder);
867 }
868
869 void
870 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
871                                                gpointer user_data)
872 {
873         const GError *error;
874         GObject *win = modest_mail_operation_get_source (mail_op);
875
876         error = modest_mail_operation_get_error (mail_op);
877         printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, error->code, error->message);
878  
879         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
880
881                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
882                                                         error->message);
883         } else {
884                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
885                                                         _("mail_ni_ui_folder_get_msg_folder_error"));
886         }
887
888         if (win)
889                 g_object_unref (win);
890 }
891
892 /*
893  * This function is used by both modest_ui_actions_on_open and
894  * modest_ui_actions_on_header_activated. This way we always do the
895  * same when trying to open messages.
896  */
897 static void
898 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
899 {
900         ModestWindowMgr *mgr = NULL;
901         TnyIterator *iter = NULL;
902         ModestMailOperation *mail_op = NULL;
903         TnyList *not_opened_headers = NULL;
904         TnyHeaderFlags flags = 0;
905                 
906         /* Look if we already have a message view for each header. If
907            true, then remove the header from the list of headers to
908            open */
909         mgr = modest_runtime_get_window_mgr ();
910         iter = tny_list_create_iterator (headers);
911         not_opened_headers = tny_simple_list_new ();
912
913         while (!tny_iterator_is_done (iter)) {
914
915                 ModestWindow *window = NULL;
916                 TnyHeader *header = NULL;
917                 gboolean found = FALSE;
918                 
919                 header = TNY_HEADER (tny_iterator_get_current (iter));
920                 if (header)
921                         flags = tny_header_get_flags (header);
922
923                 window = NULL;
924                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
925                 
926                 /* Do not open again the message and present the
927                    window to the user */
928                 if (found) {
929                         if (window)
930                                 gtk_window_present (GTK_WINDOW (window));
931                         else
932                                 /* the header has been registered already, we don't do
933                                  * anything but wait for the window to come up*/
934                                 g_debug ("header %p already registered, waiting for window", header);
935                 } else {
936                         tny_list_append (not_opened_headers, G_OBJECT (header));
937                 }
938
939                 if (header)
940                         g_object_unref (header);
941
942                 tny_iterator_next (iter);
943         }
944         g_object_unref (iter);
945         iter = NULL;
946         
947         /* If some messages would have to be downloaded, ask the user to 
948          * make a connection. It's generally easier to do this here (in the mainloop) 
949          * than later in a thread:
950          */
951         if (tny_list_get_length (not_opened_headers) > 0) {
952                 TnyIterator *iter;
953                 gboolean found = FALSE;
954
955                 iter = tny_list_create_iterator (not_opened_headers);
956                 while (!tny_iterator_is_done (iter) && !found) {
957                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
958                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
959                                 found = TRUE;
960                         else
961                                 tny_iterator_next (iter);
962
963                         g_object_unref (header);
964                 }
965                 g_object_unref (iter);
966
967                 if (found && !modest_platform_connect_and_wait (GTK_WINDOW (win), NULL)) {
968                         g_object_unref (not_opened_headers);
969                         return;                 
970                 }
971         }
972         
973         /* Register the headers before actually creating the windows: */
974         TnyIterator *iter_not_opened = tny_list_create_iterator (not_opened_headers);
975         while (!tny_iterator_is_done (iter_not_opened)) {
976                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
977                 if (header) {
978                         modest_window_mgr_register_header (mgr, header);
979                         g_object_unref (header);
980                 }
981                 
982                 tny_iterator_next (iter_not_opened);
983         }
984         g_object_unref (iter_not_opened);
985         iter_not_opened = NULL;
986         
987         /* Open each message */
988         if (tny_list_get_length (not_opened_headers) > 0) {
989                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
990                                                                          G_OBJECT (win), 
991                                                                          modest_ui_actions_get_msgs_full_error_handler, 
992                                                                          NULL);
993                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
994                 if (tny_list_get_length (not_opened_headers) > 1) {
995                         modest_mail_operation_get_msgs_full (mail_op, 
996                                                              not_opened_headers, 
997                                                              open_msg_cb, 
998                                                              NULL, 
999                                                              NULL);
1000                 } else {
1001                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1002                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1003                         modest_mail_operation_get_msg (mail_op, header, open_msg_cb, NULL);
1004                         g_object_unref (header);
1005                         g_object_unref (iter);
1006                 }
1007                 g_object_unref (mail_op);
1008         }
1009
1010         /* Clean */
1011         if (not_opened_headers != NULL)
1012                 g_object_unref (not_opened_headers);
1013 }
1014
1015 void
1016 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1017 {
1018         TnyList *headers;
1019
1020         /* Get headers */
1021         headers = get_selected_headers (win);
1022         if (!headers)
1023                 return;
1024
1025         /* Open them */
1026         _modest_ui_actions_open (headers, win);
1027
1028         g_object_unref(headers);
1029 }
1030
1031
1032 static void
1033 free_reply_forward_helper (gpointer data)
1034 {
1035         ReplyForwardHelper *helper;
1036
1037         helper = (ReplyForwardHelper *) data;
1038         g_free (helper->account_name);
1039         g_slice_free (ReplyForwardHelper, helper);
1040 }
1041
1042 static void
1043 reply_forward_cb (ModestMailOperation *mail_op, 
1044                   TnyHeader *header, 
1045                   TnyMsg *msg,
1046                   gpointer user_data)
1047 {
1048         TnyMsg *new_msg;
1049         ReplyForwardHelper *rf_helper;
1050         ModestWindow *msg_win = NULL;
1051         ModestEditType edit_type;
1052         gchar *from = NULL;
1053         TnyAccount *account = NULL;
1054         ModestWindowMgr *mgr = NULL;
1055         gchar *signature = NULL;
1056
1057         /* If there was any error. The mail operation could be NULL,
1058            this means that we already have the message downloaded and
1059            that we didn't do a mail operation to retrieve it */
1060         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1061                 return;
1062                         
1063         g_return_if_fail (user_data != NULL);
1064         rf_helper = (ReplyForwardHelper *) user_data;
1065
1066         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1067                                                    rf_helper->account_name);
1068         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
1069                                          rf_helper->account_name,
1070                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
1071                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
1072                                                            rf_helper->account_name,
1073                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
1074         }
1075
1076         /* Create reply mail */
1077         switch (rf_helper->action) {
1078         case ACTION_REPLY:
1079                 new_msg = 
1080                         modest_tny_msg_create_reply_msg (msg, header, from, signature,
1081                                                          rf_helper->reply_forward_type,
1082                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1083                 break;
1084         case ACTION_REPLY_TO_ALL:
1085                 new_msg = 
1086                         modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1087                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1088                 edit_type = MODEST_EDIT_TYPE_REPLY;
1089                 break;
1090         case ACTION_FORWARD:
1091                 new_msg = 
1092                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1093                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1094                 break;
1095         default:
1096                 g_return_if_reached ();
1097                 return;
1098         }
1099
1100         g_free (signature);
1101
1102         if (!new_msg) {
1103                 g_printerr ("modest: failed to create message\n");
1104                 goto cleanup;
1105         }
1106
1107         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1108                                                                        rf_helper->account_name,
1109                                                                        TNY_ACCOUNT_TYPE_STORE);
1110         if (!account) {
1111                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1112                 goto cleanup;
1113         }
1114
1115         /* Create and register the windows */
1116         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1117         mgr = modest_runtime_get_window_mgr ();
1118         modest_window_mgr_register_window (mgr, msg_win);
1119
1120         if (rf_helper->parent_window != NULL) {
1121                 gdouble parent_zoom;
1122
1123                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1124                 modest_window_set_zoom (msg_win, parent_zoom);
1125         }
1126
1127         /* Show edit window */
1128         gtk_widget_show_all (GTK_WIDGET (msg_win));
1129
1130 cleanup:
1131         if (msg_win)
1132                 g_object_unref (msg_win);
1133         if (new_msg)
1134                 g_object_unref (G_OBJECT (new_msg));
1135         if (account)
1136                 g_object_unref (G_OBJECT (account));
1137 /*      g_object_unref (msg); */
1138         free_reply_forward_helper (rf_helper);
1139 }
1140
1141 /*
1142  * Checks a list of headers. If any of them are not currently
1143  * downloaded (CACHED) then it asks the user for permission to
1144  * download them.
1145  *
1146  * Returns FALSE if the user does not want to download the
1147  * messages. Returns TRUE if the user allowed the download or if all
1148  * of them are currently downloaded
1149  */
1150 static gboolean
1151 download_uncached_messages (TnyList *header_list, 
1152                             GtkWindow *win,
1153                             gboolean reply_fwd)
1154 {
1155         TnyIterator *iter;
1156         gboolean retval;
1157         gint uncached_messages = 0;
1158
1159         iter = tny_list_create_iterator (header_list);
1160         while (!tny_iterator_is_done (iter)) {
1161                 TnyHeader *header;
1162
1163                 header = TNY_HEADER (tny_iterator_get_current (iter));
1164                 if (header) {
1165                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1166                                 uncached_messages ++;
1167                         g_object_unref (header);
1168                 }
1169
1170                 tny_iterator_next (iter);
1171         }
1172         g_object_unref (iter);
1173
1174         /* Ask for user permission to download the messages */
1175         retval = TRUE;
1176         if (uncached_messages > 0) {
1177                 GtkResponseType response;
1178                 if (reply_fwd)
1179                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1180                                                                             _("emev_nc_include_original"));
1181                 else
1182                         response =
1183                                 modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1184                                                                          ngettext("mcen_nc_get_msg",
1185                                                                                   "mcen_nc_get_msgs",
1186                                                                                   uncached_messages));
1187                 if (response == GTK_RESPONSE_CANCEL)
1188                         retval = FALSE;
1189                 else {
1190                         /* If a download will be necessary, make sure that we have a connection: */
1191                         retval = modest_platform_connect_and_wait(win, NULL);   
1192                 }
1193         }
1194         return retval;
1195 }
1196
1197
1198 /*
1199  * Common code for the reply and forward actions
1200  */
1201 static void
1202 reply_forward (ReplyForwardAction action, ModestWindow *win)
1203 {
1204         ModestMailOperation *mail_op = NULL;
1205         TnyList *header_list = NULL;
1206         ReplyForwardHelper *rf_helper = NULL;
1207         guint reply_forward_type;
1208         gboolean continue_download = TRUE;
1209         gboolean do_retrieve = TRUE;
1210         
1211         g_return_if_fail (MODEST_IS_WINDOW(win));
1212
1213         /* we need an account when editing */
1214         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1215                 run_account_setup_wizard (win);
1216                 return;
1217         }
1218         
1219         header_list = get_selected_headers (win);
1220         if (!header_list)
1221                 return;
1222
1223         reply_forward_type = 
1224                 modest_conf_get_int (modest_runtime_get_conf (),
1225                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1226                                      NULL);
1227
1228         /* Check that the messages have been previously downloaded */
1229         do_retrieve = (action == ACTION_FORWARD) || (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1230         if (do_retrieve)
1231                 continue_download = download_uncached_messages (header_list, GTK_WINDOW (win), TRUE);
1232         if (!continue_download) {
1233                 g_object_unref (header_list);
1234                 return;
1235         }
1236         
1237         /* We assume that we can only select messages of the
1238            same folder and that we reply all of them from the
1239            same account. In fact the interface currently only
1240            allows single selection */
1241         
1242         /* Fill helpers */
1243         rf_helper = g_slice_new0 (ReplyForwardHelper);
1244         rf_helper->reply_forward_type = reply_forward_type;
1245         rf_helper->action = action;
1246         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1247         
1248         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1249                 rf_helper->parent_window = GTK_WIDGET (win);
1250         if (!rf_helper->account_name)
1251                 rf_helper->account_name =
1252                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1253
1254         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1255                 TnyMsg *msg;
1256                 TnyHeader *header;
1257                 /* Get header and message. Do not free them here, the
1258                    reply_forward_cb must do it */
1259                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1260                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1261                 if (!msg || !header) {
1262                         if (msg)
1263                                 g_object_unref (msg);
1264                         g_printerr ("modest: no message found\n");
1265                         return;
1266                 } else {
1267                         reply_forward_cb (NULL, header, msg, rf_helper);
1268                 }
1269                 if (header)
1270                         g_object_unref (header);
1271         } else {
1272                 TnyHeader *header;
1273                 TnyIterator *iter;
1274
1275                 /* Only reply/forward to one message */
1276                 iter = tny_list_create_iterator (header_list);
1277                 header = TNY_HEADER (tny_iterator_get_current (iter));
1278                 g_object_unref (iter);
1279
1280                 if (header) {
1281                         /* Retrieve messages */
1282                         if (do_retrieve) {
1283                                 mail_op = modest_mail_operation_new_with_error_handling (
1284                                         MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1285                                         G_OBJECT(win),
1286                                         modest_ui_actions_get_msgs_full_error_handler, 
1287                                         NULL);
1288                                 modest_mail_operation_queue_add (
1289                                         modest_runtime_get_mail_operation_queue (), mail_op);
1290                                 
1291                                 modest_mail_operation_get_msg (mail_op,
1292                                                                header,
1293                                                                reply_forward_cb,
1294                                                                rf_helper);
1295                                 /* Clean */
1296                                 g_object_unref(mail_op);
1297                         } else {
1298                                 /* we put a ref here to prevent double unref as the reply
1299                                  * forward callback unrefs the header at its end */
1300                                 reply_forward_cb (NULL, header, NULL, rf_helper);
1301                         }
1302
1303
1304                         g_object_unref (header);
1305                 }
1306
1307         }
1308
1309         /* Free */
1310         g_object_unref (header_list);
1311 }
1312
1313 void
1314 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1315 {
1316         g_return_if_fail (MODEST_IS_WINDOW(win));
1317
1318         reply_forward (ACTION_REPLY, win);
1319 }
1320
1321 void
1322 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1323 {
1324         g_return_if_fail (MODEST_IS_WINDOW(win));
1325
1326         reply_forward (ACTION_FORWARD, win);
1327 }
1328
1329 void
1330 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1331 {
1332         g_return_if_fail (MODEST_IS_WINDOW(win));
1333
1334         reply_forward (ACTION_REPLY_TO_ALL, win);
1335 }
1336
1337 void 
1338 modest_ui_actions_on_next (GtkAction *action, 
1339                            ModestWindow *window)
1340 {
1341         if (MODEST_IS_MAIN_WINDOW (window)) {
1342                 GtkWidget *header_view;
1343
1344                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1345                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1346                 if (!header_view)
1347                         return;
1348         
1349                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
1350         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1351                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
1352         } else {
1353                 g_return_if_reached ();
1354         }
1355 }
1356
1357 void 
1358 modest_ui_actions_on_prev (GtkAction *action, 
1359                            ModestWindow *window)
1360 {
1361         g_return_if_fail (MODEST_IS_WINDOW(window));
1362
1363         if (MODEST_IS_MAIN_WINDOW (window)) {
1364                 GtkWidget *header_view;
1365                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1366                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1367                 if (!header_view)
1368                         return;
1369                 
1370                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1371         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1372                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1373         } else {
1374                 g_return_if_reached ();
1375         }
1376 }
1377
1378 void 
1379 modest_ui_actions_on_sort (GtkAction *action, 
1380                            ModestWindow *window)
1381 {
1382         g_return_if_fail (MODEST_IS_WINDOW(window));
1383
1384         if (MODEST_IS_MAIN_WINDOW (window)) {
1385                 GtkWidget *header_view;
1386                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1387                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1388                 if (!header_view) {
1389                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1390
1391                         return;
1392                 }
1393
1394                 /* Show sorting dialog */
1395                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1396         }
1397 }
1398
1399 static void
1400 new_messages_arrived (ModestMailOperation *self, 
1401                       gint new_messages,
1402                       gpointer user_data)
1403 {
1404         if (new_messages == 0)
1405                 return;
1406
1407         modest_platform_on_new_msg ();
1408 }
1409
1410 /*
1411  * This function performs the send & receive required actions. The
1412  * window is used to create the mail operation. Typically it should
1413  * always be the main window, but we pass it as argument in order to
1414  * be more flexible.
1415  */
1416 void
1417 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1418 {
1419         gchar *acc_name = NULL;
1420         ModestMailOperation *mail_op;
1421
1422         /* If no account name was provided then get the current account, and if
1423            there is no current account then pick the default one: */
1424         if (!account_name) {
1425                 acc_name = g_strdup (modest_window_get_active_account(win));
1426                 if (!acc_name)
1427                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1428                 if (!acc_name) {
1429                         g_printerr ("modest: cannot get default account\n");
1430                         return;
1431                 }
1432         } else {
1433                 acc_name = g_strdup (account_name);
1434         }
1435
1436         /* Set send/receive operation in progress */    
1437         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1438
1439         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1440                                                                  G_OBJECT (win),
1441                                                                  modest_ui_actions_send_receive_error_handler,
1442                                                                  NULL);
1443
1444         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1445                           G_CALLBACK (_on_send_receive_progress_changed), 
1446                           win);
1447
1448         /* Send & receive. */
1449         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1450         /* Receive and then send. The operation is tagged initially as
1451            a receive operation because the account update performs a
1452            receive and then a send. The operation changes its type
1453            internally, so the progress objects will receive the proper
1454            progress information */
1455         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1456         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, NULL);
1457         g_object_unref (G_OBJECT (mail_op));
1458         
1459         /* Free */
1460         g_free (acc_name);
1461 }
1462
1463
1464 static void
1465 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1466                                   ModestWindow *win)
1467 {
1468         TnyTransportAccount *transport_account;
1469         TnySendQueue *send_queue = NULL;
1470         GError *error = NULL;
1471
1472         /* Get transport account */
1473         transport_account =
1474                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1475                                       (modest_runtime_get_account_store(),
1476                                        account_name,
1477                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1478         if (!transport_account) {
1479                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1480                 goto frees;
1481         }
1482
1483         /* Get send queue*/
1484         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1485         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1486                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1487                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1488                              "modest: could not find send queue for account\n");
1489         } else {
1490                 /* Keeep messages in outbox folder */
1491                 tny_send_queue_cancel (send_queue, FALSE, &error);
1492         }       
1493
1494  frees:
1495         if (transport_account != NULL) 
1496                 g_object_unref (G_OBJECT (transport_account));
1497 }
1498
1499 static void
1500 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1501 {
1502         GSList *account_names, *iter;
1503
1504         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1505                                                           TRUE);
1506
1507         iter = account_names;
1508         while (iter) {                  
1509                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1510                 iter = g_slist_next (iter);
1511         }
1512
1513         modest_account_mgr_free_account_names (account_names);
1514         account_names = NULL;
1515 }
1516
1517 void
1518 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1519
1520 {
1521         /* Check if accounts exist */
1522         gboolean accounts_exist = 
1523                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1524         
1525         /* If not, allow the user to create an account before trying to send/receive. */
1526         if (!accounts_exist)
1527                 modest_ui_actions_on_accounts (NULL, win);
1528         
1529         /* Cancel all sending operaitons */     
1530         modest_ui_actions_cancel_send_all (win);
1531 }
1532
1533 /*
1534  * Refreshes all accounts. This function will be used by automatic
1535  * updates
1536  */
1537 void
1538 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1539 {
1540         GSList *account_names, *iter;
1541
1542         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1543                                                           TRUE);
1544
1545         iter = account_names;
1546         while (iter) {                  
1547                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1548                 iter = g_slist_next (iter);
1549         }
1550
1551         modest_account_mgr_free_account_names (account_names);
1552         account_names = NULL;
1553 }
1554
1555 void 
1556 modest_do_refresh_current_folder(ModestWindow *win)
1557 {
1558         /* Refresh currently selected folder. Note that if we only
1559            want to retreive the headers, then the refresh only will
1560            invoke a poke_status over all folders, i.e., only the
1561            total/unread count will be updated */
1562         if (MODEST_IS_MAIN_WINDOW (win)) {
1563                 GtkWidget *header_view, *folder_view;
1564                 TnyFolderStore *folder_store;
1565
1566                 /* Get folder and header view */
1567                 folder_view = 
1568                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1569                                                              MODEST_WIDGET_TYPE_FOLDER_VIEW);
1570
1571                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1572
1573                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1574                         header_view = 
1575                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1576                                                                      MODEST_WIDGET_TYPE_HEADER_VIEW);
1577                 
1578                         /* We do not need to set the contents style
1579                            because it hasn't changed. We also do not
1580                            need to save the widget status. Just force
1581                            a refresh */
1582                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1583                                                        TNY_FOLDER (folder_store),
1584                                                        folder_refreshed_cb,
1585                                                        MODEST_MAIN_WINDOW (win));
1586                 }
1587                 
1588                 if (folder_store)
1589                         g_object_unref (folder_store);
1590         }
1591 }
1592
1593
1594 /*
1595  * Handler of the click on Send&Receive button in the main toolbar
1596  */
1597 void
1598 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1599 {
1600         /* Check if accounts exist */
1601         gboolean accounts_exist = 
1602                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1603         
1604         /* If not, allow the user to create an account before trying to send/receive. */
1605         if (!accounts_exist)
1606                 modest_ui_actions_on_accounts (NULL, win);
1607
1608         modest_do_refresh_current_folder (win);
1609         
1610         /* Refresh the active account */
1611         modest_ui_actions_do_send_receive (NULL, win);
1612 }
1613
1614
1615 void
1616 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1617 {
1618         ModestConf *conf;
1619         GtkWidget *header_view;
1620         
1621         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1622
1623         header_view = modest_main_window_get_child_widget (main_window,
1624                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1625         if (!header_view)
1626                 return;
1627
1628         conf = modest_runtime_get_conf ();
1629         
1630         /* what is saved/restored is depending on the style; thus; we save with
1631          * old style, then update the style, and restore for this new style
1632          */
1633         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1634         
1635         if (modest_header_view_get_style
1636             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1637                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1638                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1639         else
1640                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1641                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1642
1643         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1644                                       MODEST_CONF_HEADER_VIEW_KEY);
1645 }
1646
1647
1648 void 
1649 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1650                                       TnyHeader *header,
1651                                       ModestMainWindow *main_window)
1652 {
1653         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1654         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1655         
1656         /* in the case the folder is empty, show the empty folder message and focus
1657          * folder view */
1658         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1659                 if (modest_header_view_is_empty (header_view)) {
1660                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1661                         GtkWidget *folder_view = 
1662                                 modest_main_window_get_child_widget (main_window,
1663                                                                      MODEST_WIDGET_TYPE_FOLDER_VIEW);
1664                         if (folder != NULL) 
1665                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1666                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1667                         return;
1668                 }
1669         }
1670         /* If no header has been selected then exit */
1671         if (!header)
1672                 return;
1673
1674         /* Update focus */
1675         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1676             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1677
1678         /* Update Main window title */
1679         if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
1680                 const gchar *subject = tny_header_get_subject (header);
1681                 if (subject && strlen(subject) > 0)
1682                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
1683                 else
1684                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
1685         }
1686
1687         /* Update toolbar dimming state */
1688         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1689 }
1690
1691 void
1692 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1693                                        TnyHeader *header,
1694                                        ModestMainWindow *main_window)
1695 {
1696         TnyList *headers;
1697
1698         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1699         
1700         if (!header)
1701                 return;
1702
1703         headers = tny_simple_list_new ();
1704         tny_list_prepend (headers, G_OBJECT (header));
1705
1706         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1707
1708         g_object_unref (headers);
1709 }
1710
1711 static void
1712 set_active_account_from_tny_account (TnyAccount *account,
1713                                      ModestWindow *window)
1714 {
1715         const gchar *server_acc_name = tny_account_get_id (account);
1716         
1717         /* We need the TnyAccount provided by the
1718            account store because that is the one that
1719            knows the name of the Modest account */
1720         TnyAccount *modest_server_account = modest_server_account = 
1721                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1722                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1723                                                              server_acc_name);
1724         
1725         const gchar *modest_acc_name = 
1726                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1727         modest_window_set_active_account (window, modest_acc_name);
1728         g_object_unref (modest_server_account);
1729 }
1730
1731
1732 static void
1733 folder_refreshed_cb (ModestMailOperation *mail_op, 
1734                      TnyFolder *folder, 
1735                      gpointer user_data)
1736 {
1737         ModestMainWindow *win = NULL;
1738         GtkWidget *header_view;
1739         TnyFolder *current_folder;
1740
1741         g_return_if_fail (TNY_IS_FOLDER (folder));
1742
1743         win = MODEST_MAIN_WINDOW (user_data);
1744         header_view = 
1745                 modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
1746
1747         if (header_view) {
1748                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
1749                 if (current_folder != NULL && folder != current_folder) {
1750                         return;
1751                 }
1752         }
1753
1754         /* Check if folder is empty and set headers view contents style */
1755         if (tny_folder_get_all_count (folder) == 0) {
1756         printf ("DEBUG: %s: tny_folder_get_all_count() returned 0.\n", __FUNCTION__);
1757                 modest_main_window_set_contents_style (win,
1758                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1759         } else {
1760                 printf ("DEBUG: %s: tny_folder_get_all_count() returned >0.\n", __FUNCTION__);
1761         }
1762 }
1763
1764 void 
1765 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1766                                                TnyFolderStore *folder_store, 
1767                                                gboolean selected,
1768                                                ModestMainWindow *main_window)
1769 {
1770         ModestConf *conf;
1771         GtkWidget *header_view;
1772
1773         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1774
1775         header_view = modest_main_window_get_child_widget(main_window,
1776                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1777         if (!header_view)
1778                 return;
1779         
1780         conf = modest_runtime_get_conf ();
1781
1782         if (TNY_IS_ACCOUNT (folder_store)) {
1783                 if (selected) {
1784                         /* Update active account */
1785                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1786                         /* Show account details */
1787                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1788                 }
1789         } else {
1790                 if (TNY_IS_FOLDER (folder_store) && selected) {
1791                         
1792                         /* Update the active account */
1793                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1794                         if (account) {
1795                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1796                                 g_object_unref (account);
1797                                 account = NULL;
1798                         }
1799
1800                         /* Set the header style by default, it could
1801                            be changed later by the refresh callback to
1802                            empty */
1803                         modest_main_window_set_contents_style (main_window, 
1804                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1805
1806                         /* Set folder on header view. This function
1807                            will call tny_folder_refresh_async so we
1808                            pass a callback that will be called when
1809                            finished. We use that callback to set the
1810                            empty view if there are no messages */
1811                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1812                                                        TNY_FOLDER (folder_store),
1813                                                        folder_refreshed_cb,
1814                                                        main_window);
1815                         
1816                         /* Restore configuration. We need to do this
1817                            *after* the set_folder because the widget
1818                            memory asks the header view about its
1819                            folder  */
1820                         modest_widget_memory_restore (modest_runtime_get_conf (), 
1821                                                       G_OBJECT(header_view),
1822                                                       MODEST_CONF_HEADER_VIEW_KEY);
1823                 } else {
1824                         /* Update the active account */
1825                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1826                         /* Save only if we're seeing headers */
1827                         if (modest_main_window_get_contents_style (main_window) ==
1828                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1829                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
1830                                                            MODEST_CONF_HEADER_VIEW_KEY);
1831                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
1832                 }
1833         }
1834
1835         /* Update toolbar dimming state */
1836         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1837 }
1838
1839 void 
1840 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1841                                      ModestWindow *win)
1842 {
1843         GtkWidget *dialog;
1844         gchar *txt, *item;
1845         gboolean online;
1846
1847         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1848         
1849         online = tny_device_is_online (modest_runtime_get_device());
1850
1851         if (online) {
1852                 /* already online -- the item is simply not there... */
1853                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1854                                                  GTK_DIALOG_MODAL,
1855                                                  GTK_MESSAGE_WARNING,
1856                                                  GTK_BUTTONS_OK,
1857                                                  _("The %s you selected cannot be found"),
1858                                                  item);
1859                 gtk_dialog_run (GTK_DIALOG(dialog));
1860         } else {
1861                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1862                                                       GTK_WINDOW (win),
1863                                                       GTK_DIALOG_MODAL,
1864                                                       GTK_STOCK_CANCEL,
1865                                                       GTK_RESPONSE_REJECT,
1866                                                       GTK_STOCK_OK,
1867                                                       GTK_RESPONSE_ACCEPT,
1868                                                       NULL);
1869                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1870                                          "Do you want to get online?"), item);
1871                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1872                                     gtk_label_new (txt), FALSE, FALSE, 0);
1873                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1874                 g_free (txt);
1875
1876                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1877                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1878                         /* TODO: Comment about why is this commented out: */
1879                         /* modest_platform_connect_and_wait (); */
1880                 }
1881         }
1882         gtk_widget_destroy (dialog);
1883 }
1884
1885 void
1886 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1887                                      ModestWindow *win)
1888 {
1889         /* g_message ("%s %s", __FUNCTION__, link); */
1890 }       
1891
1892
1893 void
1894 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1895                                         ModestWindow *win)
1896 {
1897         modest_platform_activate_uri (link);
1898 }
1899
1900 void
1901 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1902                                           ModestWindow *win)
1903 {
1904         modest_platform_show_uri_popup (link);
1905 }
1906
1907 void
1908 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1909                                              ModestWindow *win)
1910 {
1911         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1912 }
1913
1914 void
1915 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1916                                           const gchar *address,
1917                                           ModestWindow *win)
1918 {
1919         /* g_message ("%s %s", __FUNCTION__, address); */
1920 }
1921
1922 void
1923 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1924 {
1925         TnyTransportAccount *transport_account;
1926         ModestMailOperation *mail_operation;
1927         MsgData *data;
1928         gchar *account_name, *from;
1929         ModestAccountMgr *account_mgr;
1930         gchar *info_text = NULL;
1931
1932         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1933         
1934         data = modest_msg_edit_window_get_msg_data (edit_window);
1935
1936         account_mgr = modest_runtime_get_account_mgr();
1937         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1938         if (!account_name) 
1939                 account_name = modest_account_mgr_get_default_account (account_mgr);
1940         if (!account_name) {
1941                 g_printerr ("modest: no account found\n");
1942                 modest_msg_edit_window_free_msg_data (edit_window, data);
1943                 return;
1944         }
1945
1946         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1947                 account_name = g_strdup (data->account_name);
1948         }
1949
1950         transport_account =
1951                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1952                                       (modest_runtime_get_account_store(),
1953                                        account_name,
1954                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1955         if (!transport_account) {
1956                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1957                 g_free (account_name);
1958                 modest_msg_edit_window_free_msg_data (edit_window, data);
1959                 return;
1960         }
1961         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1962
1963         /* Create the mail operation */         
1964         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1965         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1966
1967         modest_mail_operation_save_to_drafts (mail_operation,
1968                                               transport_account,
1969                                               data->draft_msg,
1970                                               edit_window,
1971                                               from,
1972                                               data->to, 
1973                                               data->cc, 
1974                                               data->bcc,
1975                                               data->subject, 
1976                                               data->plain_body, 
1977                                               data->html_body,
1978                                               data->attachments,
1979                                               data->priority_flags);
1980         /* Frees */
1981         g_free (from);
1982         g_free (account_name);
1983         g_object_unref (G_OBJECT (transport_account));
1984         g_object_unref (G_OBJECT (mail_operation));
1985
1986         modest_msg_edit_window_free_msg_data (edit_window, data);
1987
1988         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
1989         modest_platform_information_banner (NULL, NULL, info_text);
1990         g_free (info_text);
1991 }
1992
1993 /* For instance, when clicking the Send toolbar button when editing a message: */
1994 void
1995 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1996 {
1997         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1998
1999         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2000                 return;
2001         
2002         /* Offer the connection dialog, if necessary: */        
2003         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window), NULL))
2004                 return;
2005         
2006         /* FIXME: Code added just for testing. The final version will
2007            use the send queue provided by tinymail and some
2008            classifier */
2009         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2010         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2011         if (!account_name) 
2012                 account_name = modest_account_mgr_get_default_account (account_mgr);
2013                 
2014         if (!account_name) {
2015                 /* Run account setup wizard */
2016                 run_account_setup_wizard(MODEST_WINDOW(edit_window));
2017                 return;
2018         }
2019         
2020         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2021
2022         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2023                 account_name = g_strdup (data->account_name);
2024         }
2025         
2026         /* Get the currently-active transport account for this modest account: */
2027         TnyTransportAccount *transport_account =
2028                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
2029                                       (modest_runtime_get_account_store(),
2030                                        account_name));
2031         if (!transport_account) {
2032                 /* Run account setup wizard */
2033                 run_account_setup_wizard(MODEST_WINDOW(edit_window));
2034                 return;
2035         }
2036         
2037         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2038
2039         /* mail content checks and dialogs */
2040         if (data->subject == NULL || data->subject[0] == '\0') {
2041                 GtkResponseType response;
2042                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
2043                                                                     _("mcen_nc_subject_is_empty_send"));
2044                 if (response == GTK_RESPONSE_CANCEL) {
2045                         g_free (account_name);
2046                         return;
2047                 }
2048         }
2049
2050         if (data->plain_body == NULL || data->plain_body[0] == '\0') {
2051                 GtkResponseType response;
2052                 gchar *note_message;
2053                 gchar *note_subject = data->subject;
2054                 if (note_subject == NULL || note_subject[0] == '\0')
2055                         note_subject = _("mail_va_no_subject");
2056                 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
2057                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
2058                                                                     note_message);
2059                 g_free (note_message);
2060                 if (response == GTK_RESPONSE_CANCEL) {
2061                         g_free (account_name);
2062                         return;
2063                 }
2064         }
2065
2066         modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2067
2068         /* Create the mail operation */
2069         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
2070         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2071
2072         modest_mail_operation_send_new_mail (mail_operation,
2073                                              transport_account,
2074                                              data->draft_msg,
2075                                              from,
2076                                              data->to, 
2077                                              data->cc, 
2078                                              data->bcc,
2079                                              data->subject, 
2080                                              data->plain_body, 
2081                                              data->html_body,
2082                                              data->attachments,
2083                                              data->priority_flags);
2084                                              
2085         /* Free data: */
2086         g_free (from);
2087         g_free (account_name);
2088         g_object_unref (G_OBJECT (transport_account));
2089         g_object_unref (G_OBJECT (mail_operation));
2090
2091         modest_msg_edit_window_free_msg_data (edit_window, data);
2092         modest_msg_edit_window_set_sent (edit_window, TRUE);
2093
2094         /* Save settings and close the window: */
2095         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2096 }
2097
2098 void 
2099 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2100                                   ModestMsgEditWindow *window)
2101 {
2102         ModestMsgEditFormatState *format_state = NULL;
2103
2104         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2105         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2106
2107         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2108                 return;
2109
2110         format_state = modest_msg_edit_window_get_format_state (window);
2111         g_return_if_fail (format_state != NULL);
2112
2113         format_state->bold = gtk_toggle_action_get_active (action);
2114         modest_msg_edit_window_set_format_state (window, format_state);
2115         g_free (format_state);
2116         
2117 }
2118
2119 void 
2120 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2121                                      ModestMsgEditWindow *window)
2122 {
2123         ModestMsgEditFormatState *format_state = NULL;
2124
2125         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2126         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2127
2128         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2129                 return;
2130
2131         format_state = modest_msg_edit_window_get_format_state (window);
2132         g_return_if_fail (format_state != NULL);
2133
2134         format_state->italics = gtk_toggle_action_get_active (action);
2135         modest_msg_edit_window_set_format_state (window, format_state);
2136         g_free (format_state);
2137         
2138 }
2139
2140 void 
2141 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2142                                      ModestMsgEditWindow *window)
2143 {
2144         ModestMsgEditFormatState *format_state = NULL;
2145
2146         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2147         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2148
2149         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2150                 return;
2151
2152         format_state = modest_msg_edit_window_get_format_state (window);
2153         g_return_if_fail (format_state != NULL);
2154
2155         format_state->bullet = gtk_toggle_action_get_active (action);
2156         modest_msg_edit_window_set_format_state (window, format_state);
2157         g_free (format_state);
2158         
2159 }
2160
2161 void 
2162 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2163                                      GtkRadioAction *selected,
2164                                      ModestMsgEditWindow *window)
2165 {
2166         ModestMsgEditFormatState *format_state = NULL;
2167         GtkJustification value;
2168
2169         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2170
2171         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2172                 return;
2173
2174         value = gtk_radio_action_get_current_value (selected);
2175
2176         format_state = modest_msg_edit_window_get_format_state (window);
2177         g_return_if_fail (format_state != NULL);
2178
2179         format_state->justification = value;
2180         modest_msg_edit_window_set_format_state (window, format_state);
2181         g_free (format_state);
2182 }
2183
2184 void 
2185 modest_ui_actions_on_select_editor_color (GtkAction *action,
2186                                           ModestMsgEditWindow *window)
2187 {
2188         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2189         g_return_if_fail (GTK_IS_ACTION (action));
2190
2191         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2192                 return;
2193
2194         modest_msg_edit_window_select_color (window);
2195 }
2196
2197 void 
2198 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2199                                                      ModestMsgEditWindow *window)
2200 {
2201         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2202         g_return_if_fail (GTK_IS_ACTION (action));
2203
2204         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2205                 return;
2206
2207         modest_msg_edit_window_select_background_color (window);
2208 }
2209
2210 void 
2211 modest_ui_actions_on_insert_image (GtkAction *action,
2212                                    ModestMsgEditWindow *window)
2213 {
2214         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2215         g_return_if_fail (GTK_IS_ACTION (action));
2216
2217         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2218                 return;
2219
2220         modest_msg_edit_window_insert_image (window);
2221 }
2222
2223 void 
2224 modest_ui_actions_on_attach_file (GtkAction *action,
2225                                   ModestMsgEditWindow *window)
2226 {
2227         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2228         g_return_if_fail (GTK_IS_ACTION (action));
2229
2230         modest_msg_edit_window_offer_attach_file (window);
2231 }
2232
2233 void 
2234 modest_ui_actions_on_remove_attachments (GtkAction *action,
2235                                          ModestMsgEditWindow *window)
2236 {
2237         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2238         g_return_if_fail (GTK_IS_ACTION (action));
2239
2240         modest_msg_edit_window_remove_attachments (window, NULL);
2241 }
2242
2243 static void
2244 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2245                                             gpointer user_data)
2246 {
2247         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2248         const GError *error = modest_mail_operation_get_error (mail_op);
2249
2250         if(error)
2251         {
2252                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2253                                                     modest_mail_operation_get_error (mail_op)->message);
2254         }
2255 }
2256
2257 static void
2258 modest_ui_actions_create_folder(GtkWidget *parent_window,
2259                                 GtkWidget *folder_view)
2260 {
2261         TnyFolderStore *parent_folder;
2262
2263         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2264         
2265         if (parent_folder) {
2266                 gboolean finished = FALSE;
2267                 gint result;
2268                 gchar *folder_name = NULL, *suggested_name = NULL;
2269                 const gchar *proto_str = NULL;
2270                 TnyAccount *account;
2271
2272                 if (TNY_IS_ACCOUNT (parent_folder))
2273                         account = g_object_ref (parent_folder);
2274                 else
2275                         account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2276                 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2277
2278                 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2279                     MODEST_PROTOCOL_STORE_POP) {
2280                         finished = TRUE;
2281                         hildon_banner_show_information (NULL, NULL, _("mail_in_ui_folder_create_error"));
2282                 }
2283                 g_object_unref (account);
2284
2285                 /* Run the new folder dialog */
2286                 while (!finished) {
2287                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2288                                                                         parent_folder,
2289                                                                         suggested_name,
2290                                                                         &folder_name);
2291
2292                         g_free (suggested_name);
2293                         suggested_name = NULL;
2294
2295                         if (result == GTK_RESPONSE_REJECT) {
2296                                 finished = TRUE;
2297                         } else {
2298                                 ModestMailOperation *mail_op;
2299                                 TnyFolder *new_folder = NULL;
2300
2301                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2302                                                                                           G_OBJECT(parent_window),
2303                                                                                           modest_ui_actions_new_folder_error_handler,
2304                                                                                           parent_window);
2305
2306                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2307                                                                  mail_op);
2308                                 new_folder = modest_mail_operation_create_folder (mail_op,
2309                                                                                   parent_folder,
2310                                                                                   (const gchar *) folder_name);
2311                                 if (new_folder) {
2312                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2313                                                                           new_folder, TRUE);
2314
2315                                         g_object_unref (new_folder);
2316                                         finished = TRUE;
2317                                 }
2318                                 g_object_unref (mail_op);
2319                         }
2320
2321                         suggested_name = folder_name;
2322                         folder_name = NULL;
2323                 }
2324
2325                 g_object_unref (parent_folder);
2326         }
2327 }
2328
2329 void 
2330 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2331 {
2332         GtkWidget *folder_view;
2333         
2334         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2335
2336         folder_view = modest_main_window_get_child_widget (main_window,
2337                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2338         if (!folder_view)
2339                 return;
2340
2341         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2342 }
2343
2344 static void
2345 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2346                                                gpointer user_data)
2347 {
2348         GObject *win = modest_mail_operation_get_source (mail_op);
2349         const GError *error = NULL;
2350         const gchar *message = NULL;
2351         
2352         /* Get error message */
2353         error = modest_mail_operation_get_error (mail_op);
2354         if (error != NULL && error->message != NULL) {
2355                 message = error->message;
2356         } else {
2357                 message = _("!!! FIXME: Unable to rename");
2358         }
2359         
2360         /* Show notification dialog */
2361         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
2362         g_object_unref (win);
2363 }
2364
2365 void 
2366 modest_ui_actions_on_rename_folder (GtkAction *action,
2367                                      ModestMainWindow *main_window)
2368 {
2369         TnyFolderStore *folder;
2370         GtkWidget *folder_view;
2371         GtkWidget *header_view; 
2372
2373         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2374
2375         folder_view = modest_main_window_get_child_widget (main_window,
2376                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2377         if (!folder_view)
2378                 return;
2379
2380         header_view = modest_main_window_get_child_widget (main_window,
2381                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2382         
2383         if (!header_view)
2384                 return;
2385
2386         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2387         if (!folder)
2388                 return;
2389
2390         /* Offer the connection dialog if necessary: */
2391         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2392                 g_object_unref (G_OBJECT (folder));
2393                 return;
2394         }
2395
2396         
2397         if (TNY_IS_FOLDER (folder)) {
2398                 gchar *folder_name;
2399                 gint response;
2400                 const gchar *current_name;
2401
2402                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2403                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), NULL,
2404                                                                      current_name, &folder_name);
2405
2406                 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2407                         ModestMailOperation *mail_op;
2408
2409                         mail_op = 
2410                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO, 
2411                                                                                G_OBJECT(main_window),
2412                                                                                modest_ui_actions_rename_folder_error_handler,
2413                                                                                NULL);
2414
2415
2416                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2417                                                          mail_op);
2418
2419                         modest_header_view_clear (MODEST_HEADER_VIEW (header_view));
2420                         
2421                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2422                                                           TNY_FOLDER(folder), TRUE);
2423
2424
2425                         modest_header_view_clear ((ModestHeaderView *) header_view);
2426  
2427                         modest_mail_operation_rename_folder (mail_op,
2428                                                              TNY_FOLDER (folder),
2429                                                              (const gchar *) folder_name);
2430
2431                         g_object_unref (mail_op);
2432                         g_free (folder_name);
2433                 }
2434         }
2435         g_object_unref (folder);
2436 }
2437
2438 static void
2439 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2440                                                gpointer user_data)
2441 {
2442         GObject *win = modest_mail_operation_get_source (mail_op);
2443
2444         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2445                                                 _("mail_in_ui_folder_delete_error"));
2446         g_object_unref (win);
2447 }
2448
2449 static void
2450 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2451 {
2452         TnyFolderStore *folder;
2453         GtkWidget *folder_view;
2454         gint response;
2455         gchar *message;
2456         
2457         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2458
2459         folder_view = modest_main_window_get_child_widget (main_window,
2460                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2461         if (!folder_view)
2462                 return;
2463
2464         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2465
2466         /* Show an error if it's an account */
2467         if (!TNY_IS_FOLDER (folder)) {
2468                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2469                                                         _("mail_in_ui_folder_delete_error"));
2470                 g_object_unref (G_OBJECT (folder));
2471                 return ;
2472         }
2473
2474         /* Offer the connection dialog if necessary: */
2475         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2476                 g_object_unref (G_OBJECT (folder));
2477                 return;
2478         }
2479
2480         /* Ask the user */      
2481         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2482                                     tny_folder_get_name (TNY_FOLDER (folder)));
2483         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2484                                                             (const gchar *) message);
2485         g_free (message);
2486
2487         if (response == GTK_RESPONSE_OK) {
2488                 ModestMailOperation *mail_op = 
2489                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2490                                                                        G_OBJECT(main_window),
2491                                                                        modest_ui_actions_delete_folder_error_handler,
2492                                                                        NULL);
2493
2494                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2495                                                  mail_op);
2496                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2497                 g_object_unref (G_OBJECT (mail_op));
2498         }
2499
2500         g_object_unref (G_OBJECT (folder));
2501 }
2502
2503 void 
2504 modest_ui_actions_on_delete_folder (GtkAction *action,
2505                                      ModestMainWindow *main_window)
2506 {
2507         GtkWidget *folder_view;
2508         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2509
2510         delete_folder (main_window, FALSE);
2511         folder_view = modest_main_window_get_child_widget (main_window,
2512                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2513         if (!folder_view)
2514                 return;
2515         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2516 }
2517
2518 void 
2519 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2520 {
2521         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2522         
2523         delete_folder (main_window, TRUE);
2524 }
2525
2526
2527 static void
2528 show_error (GtkWidget *parent_widget, const gchar* text)
2529 {
2530         hildon_banner_show_information(parent_widget, NULL, text);
2531         
2532 #if 0
2533         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2534         /*
2535           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2536           (GtkDialogFlags)0,
2537           GTK_MESSAGE_ERROR,
2538           GTK_BUTTONS_OK,
2539           text ));
2540         */
2541                  
2542         gtk_dialog_run (dialog);
2543         gtk_widget_destroy (GTK_WIDGET (dialog));
2544 #endif
2545 }
2546
2547 void
2548 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2549                                          const gchar* server_account_name,
2550                                          gchar **username,
2551                                          gchar **password, 
2552                                          gboolean *cancel, 
2553                                          gboolean *remember,
2554                                          ModestMainWindow *main_window)
2555 {
2556         g_return_if_fail(server_account_name);
2557         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2558         
2559         /* Initalize output parameters: */
2560         if (cancel)
2561                 *cancel = FALSE;
2562                 
2563         if (remember)
2564                 *remember = TRUE;
2565                 
2566 #ifdef MODEST_PLATFORM_MAEMO
2567         /* Maemo uses a different (awkward) button order,
2568          * It should probably just use gtk_alternative_dialog_button_order ().
2569          */
2570         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2571                                               NULL,
2572                                               GTK_DIALOG_MODAL,
2573                                               GTK_STOCK_OK,
2574                                               GTK_RESPONSE_ACCEPT,
2575                                               GTK_STOCK_CANCEL,
2576                                               GTK_RESPONSE_REJECT,
2577                                               NULL);
2578 #else
2579         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2580                                               NULL,
2581                                               GTK_DIALOG_MODAL,
2582                                               GTK_STOCK_CANCEL,
2583                                               GTK_RESPONSE_REJECT,
2584                                               GTK_STOCK_OK,
2585                                               GTK_RESPONSE_ACCEPT,
2586                                               NULL);
2587 #endif /* MODEST_PLATFORM_MAEMO */
2588
2589         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2590         
2591         gchar *server_name = modest_server_account_get_hostname (
2592                 modest_runtime_get_account_mgr(), server_account_name);
2593         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2594                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2595                 *cancel = TRUE;
2596                 return;
2597         }
2598         
2599         /* This causes a warning because the logical ID has no %s in it, 
2600          * though the translation does, but there is not much we can do about that: */
2601         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2602         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2603                             FALSE, FALSE, 0);
2604         g_free (txt);
2605         g_free (server_name);
2606         server_name = NULL;
2607
2608         /* username: */
2609         gchar *initial_username = modest_server_account_get_username (
2610                 modest_runtime_get_account_mgr(), server_account_name);
2611         
2612         GtkWidget *entry_username = gtk_entry_new ();
2613         if (initial_username)
2614                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2615         /* Dim this if a connection has ever succeeded with this username,
2616          * as per the UI spec: */
2617         const gboolean username_known = 
2618                 modest_server_account_get_username_has_succeeded(
2619                         modest_runtime_get_account_mgr(), server_account_name);
2620         gtk_widget_set_sensitive (entry_username, !username_known);
2621         
2622 #ifdef MODEST_PLATFORM_MAEMO
2623         /* Auto-capitalization is the default, so let's turn it off: */
2624         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2625         
2626         /* Create a size group to be used by all captions.
2627          * Note that HildonCaption does not create a default size group if we do not specify one.
2628          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2629         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2630         
2631         GtkWidget *caption = hildon_caption_new (sizegroup, 
2632                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2633         gtk_widget_show (entry_username);
2634         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2635                 FALSE, FALSE, MODEST_MARGIN_HALF);
2636         gtk_widget_show (caption);
2637 #else 
2638         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2639                             TRUE, FALSE, 0);
2640 #endif /* MODEST_PLATFORM_MAEMO */      
2641                             
2642         /* password: */
2643         GtkWidget *entry_password = gtk_entry_new ();
2644         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2645         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2646         
2647 #ifdef MODEST_PLATFORM_MAEMO
2648         /* Auto-capitalization is the default, so let's turn it off: */
2649         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2650                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2651         
2652         caption = hildon_caption_new (sizegroup, 
2653                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2654         gtk_widget_show (entry_password);
2655         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2656                 FALSE, FALSE, MODEST_MARGIN_HALF);
2657         gtk_widget_show (caption);
2658         g_object_unref (sizegroup);
2659 #else 
2660         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2661                             TRUE, FALSE, 0);
2662 #endif /* MODEST_PLATFORM_MAEMO */      
2663                                 
2664 /* This is not in the Maemo UI spec:
2665         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2666         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2667                             TRUE, FALSE, 0);
2668 */
2669
2670         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2671         
2672         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2673                 if (username) {
2674                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2675                         
2676                         modest_server_account_set_username (
2677                                  modest_runtime_get_account_mgr(), server_account_name, 
2678                                  *username);
2679                                  
2680                         const gboolean username_was_changed = 
2681                                 (strcmp (*username, initial_username) != 0);
2682                         if (username_was_changed) {
2683                                 g_warning ("%s: tinymail does not yet support changing the "
2684                                         "username in the get_password() callback.\n", __FUNCTION__);
2685                         }
2686                 }
2687                         
2688                 if (password) {
2689                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2690                         
2691                         /* We do not save the password in the configuration, 
2692                          * because this function is only called for passwords that should 
2693                          * not be remembered:
2694                         modest_server_account_set_password (
2695                                  modest_runtime_get_account_mgr(), server_account_name, 
2696                                  *password);
2697                         */
2698                 }
2699                 
2700                 if (cancel)
2701                         *cancel   = FALSE;
2702                         
2703         } else {
2704                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2705                 
2706                 if (username)
2707                         *username = NULL;
2708                         
2709                 if (password)
2710                         *password = NULL;
2711                         
2712                 if (cancel)
2713                         *cancel   = TRUE;
2714         }
2715
2716 /* This is not in the Maemo UI spec:
2717         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2718                 *remember = TRUE;
2719         else
2720                 *remember = FALSE;
2721 */
2722
2723         gtk_widget_destroy (dialog);
2724         
2725         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2726 }
2727
2728 void
2729 modest_ui_actions_on_cut (GtkAction *action,
2730                           ModestWindow *window)
2731 {
2732         GtkWidget *focused_widget;
2733         GtkClipboard *clipboard;
2734
2735         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2736         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2737         if (GTK_IS_EDITABLE (focused_widget)) {
2738                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2739                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2740                 gtk_clipboard_store (clipboard);
2741         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2742                 GtkTextBuffer *buffer;
2743
2744                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2745                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2746                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2747                 gtk_clipboard_store (clipboard);
2748         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2749                 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2750         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2751                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2752         }
2753 }
2754
2755 void
2756 modest_ui_actions_on_copy (GtkAction *action,
2757                            ModestWindow *window)
2758 {
2759         GtkClipboard *clipboard;
2760         GtkWidget *focused_widget;
2761
2762         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2763         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2764
2765         if (GTK_IS_LABEL (focused_widget)) {
2766                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2767                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2768                 gtk_clipboard_store (clipboard);
2769         } else if (GTK_IS_EDITABLE (focused_widget)) {
2770                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2771                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2772                 gtk_clipboard_store (clipboard);
2773         } else if (GTK_IS_HTML (focused_widget)) {
2774                 gtk_html_copy (GTK_HTML (focused_widget));
2775                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2776                 gtk_clipboard_store (clipboard);
2777         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2778                 GtkTextBuffer *buffer;
2779                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2780                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2781                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2782                 gtk_clipboard_store (clipboard);
2783         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2784                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2785                 TnyIterator *iter = tny_list_create_iterator (header_list);
2786                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2787                 
2788                 gboolean ask = FALSE;
2789                 if (header) {
2790                         TnyFolder *folder = tny_header_get_folder (header);
2791                         TnyAccount *account = tny_folder_get_account (folder);
2792                         const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2793                         /* If it's POP then ask */
2794                         ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2795                                 MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2796                         g_object_unref (account);
2797                         g_object_unref (folder);
2798                         g_object_unref (header);
2799                 }
2800
2801                 g_object_unref (iter);
2802                 
2803                 /* Check that the messages have been previously downloaded */
2804                 gboolean continue_download = TRUE;
2805                 if (ask)
2806                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window), FALSE);
2807                 if (continue_download)
2808                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2809                 g_object_unref (header_list);
2810         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2811                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2812         }    
2813
2814         /* Show information banner */
2815         modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2816         
2817 }
2818
2819 void
2820 modest_ui_actions_on_undo (GtkAction *action,
2821                            ModestWindow *window)
2822 {
2823         ModestEmailClipboard *clipboard = NULL;
2824
2825         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2826                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2827         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2828                 /* Clear clipboard source */
2829                 clipboard = modest_runtime_get_email_clipboard ();
2830                 modest_email_clipboard_clear (clipboard);               
2831         }
2832         else {
2833                 g_return_if_reached ();
2834         }
2835 }
2836
2837 void
2838 modest_ui_actions_on_redo (GtkAction *action,
2839                            ModestWindow *window)
2840 {
2841         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2842                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2843         }
2844         else {
2845                 g_return_if_reached ();
2846         }
2847 }
2848
2849
2850 static void
2851 paste_msgs_cb (const GObject *object, gpointer user_data)
2852 {
2853         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2854         g_return_if_fail (GTK_IS_WIDGET (user_data));
2855         
2856         /* destroy information note */
2857         gtk_widget_destroy (GTK_WIDGET(user_data));
2858 }
2859
2860 static void
2861 paste_as_attachment_free (gpointer data)
2862 {
2863         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
2864
2865         gtk_widget_destroy (helper->banner);
2866         g_object_unref (helper->banner);
2867         g_free (helper);
2868 }
2869
2870 static void
2871 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
2872                             TnyHeader *header,
2873                             TnyMsg *msg,
2874                             gpointer userdata)
2875 {
2876         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
2877         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
2878
2879         if (msg == NULL)
2880                 return;
2881
2882         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
2883         
2884 }
2885
2886 void
2887 modest_ui_actions_on_paste (GtkAction *action,
2888                             ModestWindow *window)
2889 {
2890         GtkWidget *focused_widget = NULL;
2891         GtkWidget *inf_note = NULL;
2892         ModestMailOperation *mail_op = NULL;
2893
2894         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2895         if (GTK_IS_EDITABLE (focused_widget)) {
2896                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2897         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2898                 ModestEmailClipboard *e_clipboard = NULL;
2899                 e_clipboard = modest_runtime_get_email_clipboard ();
2900                 if (modest_email_clipboard_cleared (e_clipboard)) {
2901                         GtkTextBuffer *buffer;
2902                         GtkClipboard *clipboard;
2903
2904                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2905                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2906                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2907                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2908                         ModestMailOperation *mail_op;
2909                         TnyFolder *src_folder;
2910                         TnyList *data;
2911                         gboolean delete;
2912                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
2913                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
2914                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
2915                                                                            _CS("ckct_nw_pasting"));
2916                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
2917                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2918                                                              G_OBJECT (window));
2919                         if (helper->banner != NULL) {
2920                                 g_object_ref (G_OBJECT (helper->banner));
2921                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
2922                                 gtk_widget_show (GTK_WIDGET (helper->banner));
2923                         }
2924
2925                         if (data != NULL) {
2926                                 modest_mail_operation_get_msgs_full (mail_op, 
2927                                                                      data,
2928                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
2929                                                                      helper,
2930                                                                      paste_as_attachment_free);
2931                         }
2932                 }
2933         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2934                 ModestEmailClipboard *clipboard = NULL;
2935                 TnyFolder *src_folder = NULL;
2936                 TnyFolderStore *folder_store = NULL;
2937                 TnyList *data = NULL;           
2938                 gboolean delete = FALSE;
2939                 
2940                 /* Check clipboard source */
2941                 clipboard = modest_runtime_get_email_clipboard ();
2942                 if (modest_email_clipboard_cleared (clipboard)) 
2943                         return;
2944                 
2945                 /* Get elements to paste */
2946                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
2947
2948                 /* Create a new mail operation */
2949                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
2950                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2951                                                  mail_op);
2952                 
2953                 /* Get destination folder */
2954                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
2955
2956                 /* Launch notification */
2957                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
2958                                                              _CS("ckct_nw_pasting"));
2959                 if (inf_note != NULL)  {
2960                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
2961                         gtk_widget_show (GTK_WIDGET(inf_note));
2962                 }
2963
2964                 /* transfer messages  */
2965                 if (data != NULL) {
2966                         modest_mail_operation_xfer_msgs (mail_op, 
2967                                                          data,
2968                                                          TNY_FOLDER (folder_store),
2969                                                          delete,
2970                                                          paste_msgs_cb,
2971                                                          inf_note);
2972                         
2973                 } else if (src_folder != NULL) {                        
2974                         modest_mail_operation_xfer_folder (mail_op, 
2975                                                            src_folder,
2976                                                            folder_store,
2977                                                            delete,
2978                                                            paste_msgs_cb,
2979                                                            inf_note);
2980                 }
2981
2982                 /* Free */
2983                 if (data != NULL) 
2984                         g_object_unref (data);
2985                 if (src_folder != NULL) 
2986                         g_object_unref (src_folder);
2987                 if (folder_store != NULL) 
2988                         g_object_unref (folder_store);
2989         }
2990 }
2991
2992
2993 void
2994 modest_ui_actions_on_select_all (GtkAction *action,
2995                                  ModestWindow *window)
2996 {
2997         GtkWidget *focused_widget;
2998
2999         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3000         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3001                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3002         } else if (GTK_IS_LABEL (focused_widget)) {
3003                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3004         } else if (GTK_IS_EDITABLE (focused_widget)) {
3005                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3006         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3007                 GtkTextBuffer *buffer;
3008                 GtkTextIter start, end;
3009
3010                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3011                 gtk_text_buffer_get_start_iter (buffer, &start);
3012                 gtk_text_buffer_get_end_iter (buffer, &end);
3013                 gtk_text_buffer_select_range (buffer, &start, &end);
3014         } else if (GTK_IS_HTML (focused_widget)) {
3015                 gtk_html_select_all (GTK_HTML (focused_widget));
3016         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3017                 GtkWidget *header_view = focused_widget;
3018                 GtkTreeSelection *selection = NULL;
3019                 
3020                 if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
3021                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3022                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3023                                 
3024                 /* Select all messages */
3025                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3026                 gtk_tree_selection_select_all (selection);
3027
3028                 /* Set focuse on header view */
3029                 gtk_widget_grab_focus (header_view);
3030         }
3031
3032 }
3033
3034 void
3035 modest_ui_actions_on_mark_as_read (GtkAction *action,
3036                                    ModestWindow *window)
3037 {       
3038         g_return_if_fail (MODEST_IS_WINDOW(window));
3039                 
3040         /* Mark each header as read */
3041         do_headers_action (window, headers_action_mark_as_read, NULL);
3042 }
3043
3044 void
3045 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3046                                      ModestWindow *window)
3047 {       
3048         g_return_if_fail (MODEST_IS_WINDOW(window));
3049                 
3050         /* Mark each header as read */
3051         do_headers_action (window, headers_action_mark_as_unread, NULL);
3052 }
3053
3054 void
3055 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3056                                   GtkRadioAction *selected,
3057                                   ModestWindow *window)
3058 {
3059         gint value;
3060
3061         value = gtk_radio_action_get_current_value (selected);
3062         if (MODEST_IS_WINDOW (window)) {
3063                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3064         }
3065 }
3066
3067 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3068                                                         GtkRadioAction *selected,
3069                                                         ModestWindow *window)
3070 {
3071         TnyHeaderFlags flags;
3072         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3073
3074         flags = gtk_radio_action_get_current_value (selected);
3075         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3076 }
3077
3078 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3079                                                            GtkRadioAction *selected,
3080                                                            ModestWindow *window)
3081 {
3082         gint file_format;
3083
3084         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3085
3086         file_format = gtk_radio_action_get_current_value (selected);
3087         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3088 }
3089
3090
3091 void     
3092 modest_ui_actions_on_zoom_plus (GtkAction *action,
3093                                 ModestWindow *window)
3094 {
3095         g_return_if_fail (MODEST_IS_WINDOW (window));
3096
3097         modest_window_zoom_plus (MODEST_WINDOW (window));
3098 }
3099
3100 void     
3101 modest_ui_actions_on_zoom_minus (GtkAction *action,
3102                                  ModestWindow *window)
3103 {
3104         g_return_if_fail (MODEST_IS_WINDOW (window));
3105
3106         modest_window_zoom_minus (MODEST_WINDOW (window));
3107 }
3108
3109 void     
3110 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3111                                            ModestWindow *window)
3112 {
3113         ModestWindowMgr *mgr;
3114         gboolean fullscreen, active;
3115         g_return_if_fail (MODEST_IS_WINDOW (window));
3116
3117         mgr = modest_runtime_get_window_mgr ();
3118
3119         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3120         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3121
3122         if (active != fullscreen) {
3123                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3124                 gtk_window_present (GTK_WINDOW (window));
3125         }
3126 }
3127
3128 void
3129 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3130                                         ModestWindow *window)
3131 {
3132         ModestWindowMgr *mgr;
3133         gboolean fullscreen;
3134
3135         g_return_if_fail (MODEST_IS_WINDOW (window));
3136
3137         mgr = modest_runtime_get_window_mgr ();
3138         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3139         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3140
3141         gtk_window_present (GTK_WINDOW (window));
3142 }
3143
3144 /* 
3145  * Used by modest_ui_actions_on_details to call do_headers_action 
3146  */
3147 static void
3148 headers_action_show_details (TnyHeader *header, 
3149                              ModestWindow *window,
3150                              gpointer user_data)
3151
3152 {
3153         GtkWidget *dialog;
3154         
3155         /* Create dialog */
3156         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3157
3158         /* Run dialog */
3159         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3160         gtk_widget_show_all (dialog);
3161         gtk_dialog_run (GTK_DIALOG (dialog));
3162
3163         gtk_widget_destroy (dialog);
3164 }
3165
3166 /*
3167  * Show the folder details in a ModestDetailsDialog widget
3168  */
3169 static void
3170 show_folder_details (TnyFolder *folder, 
3171                      GtkWindow *window)
3172 {
3173         GtkWidget *dialog;
3174         
3175         /* Create dialog */
3176         dialog = modest_details_dialog_new_with_folder (window, folder);
3177
3178         /* Run dialog */
3179         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3180         gtk_widget_show_all (dialog);
3181         gtk_dialog_run (GTK_DIALOG (dialog));
3182
3183         gtk_widget_destroy (dialog);
3184 }
3185
3186 /*
3187  * Show the header details in a ModestDetailsDialog widget
3188  */
3189 void     
3190 modest_ui_actions_on_details (GtkAction *action, 
3191                               ModestWindow *win)
3192 {
3193         TnyList * headers_list;
3194         TnyIterator *iter;
3195         TnyHeader *header;              
3196
3197         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3198                 TnyMsg *msg;
3199
3200                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3201                 if (!msg)
3202                         return;
3203                 g_object_unref (msg);           
3204
3205                 headers_list = get_selected_headers (win);
3206                 if (!headers_list)
3207                         return;
3208
3209                 iter = tny_list_create_iterator (headers_list);
3210
3211                 header = TNY_HEADER (tny_iterator_get_current (iter));
3212                 if (header) {
3213                         headers_action_show_details (header, win, NULL);
3214                         g_object_unref (header);
3215                 }
3216
3217                 g_object_unref (iter);
3218                 g_object_unref (headers_list);
3219
3220         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3221                 GtkWidget *folder_view, *header_view;
3222
3223                 /* Check which widget has the focus */
3224                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),