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