* Commented the popup-menu
[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 <string.h>
36 #include <modest-runtime.h>
37 #include <modest-tny-msg.h>
38 #include <modest-tny-account.h>
39
40 #include "modest-ui-actions.h"
41
42 #include "modest-tny-platform-factory.h"
43
44 #include <widgets/modest-main-window.h>
45 #include <widgets/modest-msg-view-window.h>
46 #include <widgets/modest-account-view-window.h>
47
48 #include "modest-account-mgr-helpers.h"
49 #include "modest-mail-operation.h"
50 #include <modest-widget-memory.h>
51 #include <tny-error.h>
52 #include <tny-simple-list.h>
53 #include <tny-msg-view.h>
54 #include <tny-device.h>
55
56
57 typedef struct _GetMsgAsyncHelper {
58         ModestWindow *window;
59         TnyIterator *iter;
60         GFunc func;
61         gpointer user_data;
62 } GetMsgAsyncHelper;
63
64 typedef enum _ReplyForwardAction {
65         ACTION_REPLY,
66         ACTION_REPLY_TO_ALL,
67         ACTION_FORWARD
68 } ReplyForwardAction;
69
70 typedef struct _ReplyForwardHelper {
71 guint reply_forward_type;
72         ReplyForwardAction action;
73         gchar *account_name;
74 } ReplyForwardHelper;
75
76
77 static void     reply_forward_func     (gpointer data, gpointer user_data);
78 static void     read_msg_func          (gpointer data, gpointer user_data);
79 static void     get_msg_cb             (TnyFolder *folder, TnyMsg *msg, GError **err, 
80                                         gpointer user_data);
81 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
82 static gchar*   ask_for_folder_name    (GtkWindow *parent_window, const gchar *title);
83
84
85 void   
86 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
87 {
88         GtkWidget *about;
89         const gchar *authors[] = {
90                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
91                 NULL
92         };
93         about = gtk_about_dialog_new ();
94         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
95         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
96         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
97                                         _("Copyright (c) 2006, Nokia Corporation\n"
98                                           "All rights reserved."));
99         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
100                                        _("a modest e-mail client\n\n"
101                                          "design and implementation: Dirk-Jan C. Binnema\n"
102                                          "contributions from the fine people at KernelConcepts and Igalia\n"
103                                          "uses the tinymail email framework written by Philip van Hoof"));
104         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
105         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
106         
107         gtk_dialog_run (GTK_DIALOG (about));
108         gtk_widget_destroy(about);
109 }
110
111
112 static TnyList *
113 get_selected_headers (ModestWindow *win)
114 {
115         if (MODEST_IS_MAIN_WINDOW(win)) {
116                 GtkWidget *header_view;         
117                 
118                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
119                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
120                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
121                 
122         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
123                 /* for MsgViewWindows, we simply return a list with one element */
124                 TnyMsg *msg;
125                 TnyHeader *header;
126                 TnyList *list = NULL;
127                 
128                 msg  = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
129                 if (msg) {
130                         header = tny_msg_get_header (msg);
131                         list = tny_simple_list_new ();
132                         tny_list_prepend (list, G_OBJECT(header));
133                         g_object_unref (G_OBJECT(header));
134                 }
135                 return list;
136
137         } else
138                 return NULL;
139 }
140
141 void
142 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
143 {
144         TnyList *header_list;
145         TnyIterator *iter;
146
147         g_return_if_fail (MODEST_IS_WINDOW(win));
148                 
149         header_list = get_selected_headers (win);
150         
151         if (header_list) {
152                 iter = tny_list_create_iterator (header_list);
153                 do {
154                         TnyHeader *header;
155                         ModestMailOperation *mail_op;
156
157                         header = TNY_HEADER (tny_iterator_get_current (iter));
158                         /* TODO: thick grain mail operation involving
159                            a list of objects. Composite pattern ??? */
160                         mail_op = modest_mail_operation_new ();
161
162                         /* TODO: add confirmation dialog */
163
164                         /* Move to trash. TODO: Still not supported */
165                         modest_mail_operation_remove_msg (mail_op, header, FALSE);
166
167                         if (modest_mail_operation_get_status (mail_op) !=
168                             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
169                                 const GError *error;
170                                 error = modest_mail_operation_get_error (mail_op);
171                                 if (error)
172                                         g_warning (error->message);
173                         }
174
175                         g_object_unref (G_OBJECT (mail_op));
176                         g_object_unref (header);
177                         tny_iterator_next (iter);
178
179                 } while (!tny_iterator_is_done (iter));
180         }
181 }
182
183
184 void
185 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
186 {
187         /* FIXME: save size of main window */
188 /*      save_sizes (main_window); */
189         gtk_widget_destroy (GTK_WIDGET (win));
190 }
191
192 void
193 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
194 {
195         /* GtkDialog *account_win; */
196 /*      account_win = GTK_DIALOG(modest_account_view_window_new ()); */
197         
198
199 /*      gtk_dialog_run (account_win); */
200         //gtk_widget_destroy (GTK_WIDGET(account_win));
201  GtkWidget *dialog, *label;
202    
203    /* Create the widgets */
204    
205    dialog = gtk_dialog_new_with_buttons ("Message",
206                                          GTK_WINDOW(win),
207                                          GTK_DIALOG_DESTROY_WITH_PARENT,
208                                          GTK_STOCK_OK,
209                                          GTK_RESPONSE_NONE,
210                                          NULL);
211    label = gtk_label_new ("Hello World!");
212    
213    /* Ensure that the dialog box is destroyed when the user responds. */
214    
215    g_signal_connect_swapped (dialog, "response", 
216                              G_CALLBACK (gtk_widget_destroy),
217                              dialog);
218
219    /* Add the label, and show everything we've added to the dialog. */
220
221    gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
222                       label);
223    gtk_widget_show_all (dialog);
224 }
225
226 void
227 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
228 {
229         ModestWindow *msg_win;
230         TnyMsg *msg = NULL;
231         TnyFolder *folder = NULL;
232         gchar *account_name = NULL;
233         gchar *from_str = NULL;
234         GError *err = NULL;
235         TnyAccount *account;
236         
237         account_name = g_strdup(modest_window_get_active_account (win));
238         if (!account_name)
239                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
240         
241         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
242                                                                        account_name,
243                                                                        TNY_ACCOUNT_TYPE_STORE);
244         if (!account) {
245                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
246                 goto cleanup;
247         }
248
249         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
250
251         msg    = modest_tny_msg_new ("", from_str, "", "", "", "", NULL);
252         if (!msg) {
253                 g_printerr ("modest: failed to create new msg\n");
254                 goto cleanup;
255         }
256         
257         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
258         if (!folder) {
259                 g_printerr ("modest: failed to find Drafts folder\n");
260                 goto cleanup;
261         }
262         
263         tny_folder_add_msg (folder, msg, &err);
264         if (err) {
265                 g_printerr ("modest: error adding msg to Drafts folder: %s",
266                             err->message);
267                 g_error_free (err);
268                 goto cleanup;
269         }
270
271         msg_win = modest_msg_edit_window_new (msg, account_name);
272         if (win)
273                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
274                                               GTK_WINDOW (win));        
275         gtk_widget_show_all (GTK_WIDGET (msg_win));
276
277 cleanup:
278         g_free (account_name);
279         g_free (from_str);
280         if (account)
281                 g_object_unref (G_OBJECT(account));
282         if (msg)
283                 g_object_unref (G_OBJECT(msg));
284         if (folder)
285                 g_object_unref (G_OBJECT(folder));
286 }
287
288
289 void
290 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
291 {
292         modest_runtime_not_implemented (GTK_WINDOW(win)); /* FIXME */
293 }
294
295
296
297 static void
298 reply_forward_func (gpointer data, gpointer user_data)
299 {
300         TnyMsg *msg, *new_msg;
301         GetMsgAsyncHelper *helper;
302         ReplyForwardHelper *rf_helper;
303         ModestWindow *msg_win;
304         ModestEditType edit_type;
305         gchar *from;
306         GError *err = NULL;
307         TnyFolder *folder = NULL;
308         TnyAccount *account = NULL;
309         
310         msg = TNY_MSG (data);
311         helper = (GetMsgAsyncHelper *) user_data;
312         rf_helper = (ReplyForwardHelper *) helper->user_data;
313
314         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
315                                                    rf_helper->account_name);
316         /* Create reply mail */
317         switch (rf_helper->action) {
318         case ACTION_REPLY:
319                 new_msg = 
320                         modest_mail_operation_create_reply_mail (msg,  from, 
321                                                                  rf_helper->reply_forward_type,
322                                                                  MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
323                 break;
324         case ACTION_REPLY_TO_ALL:
325                 new_msg = 
326                         modest_mail_operation_create_reply_mail (msg, from, rf_helper->reply_forward_type,
327                                                                  MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
328                 edit_type = MODEST_EDIT_TYPE_REPLY;
329                 break;
330         case ACTION_FORWARD:
331                 new_msg = 
332                         modest_mail_operation_create_forward_mail (msg, from, rf_helper->reply_forward_type);
333                 edit_type = MODEST_EDIT_TYPE_FORWARD;
334                 break;
335         default:
336                 g_return_if_reached ();
337                 return;
338         }
339
340         if (!new_msg) {
341                 g_printerr ("modest: failed to create message\n");
342                 goto cleanup;
343         }
344
345         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
346                                                                        rf_helper->account_name,
347                                                                        TNY_ACCOUNT_TYPE_STORE);
348         if (!account) {
349                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
350                 goto cleanup;
351         }
352
353         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
354         if (!folder) {
355                 g_printerr ("modest: failed to find Drafts folder\n");
356                 goto cleanup;
357         }
358         
359         tny_folder_add_msg (folder, msg, &err);
360         if (err) {
361                 g_printerr ("modest: error adding msg to Drafts folder: %s",
362                             err->message);
363                 g_error_free (err);
364                 goto cleanup;
365         }       
366                         
367         /* Show edit window */
368         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
369         gtk_widget_show_all (GTK_WIDGET (msg_win));
370
371 cleanup:
372         if (new_msg)
373                 g_object_unref (G_OBJECT (new_msg));
374         if (folder)
375                 g_object_unref (G_OBJECT (folder));
376         if (account)
377                 g_object_unref (G_OBJECT (account));
378         
379         g_free (rf_helper->account_name);
380         g_slice_free (ReplyForwardHelper, rf_helper);
381 }
382 /*
383  * Common code for the reply and forward actions
384  */
385 static void
386 reply_forward (ReplyForwardAction action, ModestWindow *win)
387 {
388         TnyList *header_list;
389         guint reply_forward_type;
390         TnyHeader *header;
391         TnyFolder *folder;
392         GetMsgAsyncHelper *helper;
393         ReplyForwardHelper *rf_helper;
394         
395         g_return_if_fail (MODEST_IS_WINDOW(win));
396
397         header_list = get_selected_headers (win);
398         if (!header_list)
399                 return;
400         
401         reply_forward_type = modest_conf_get_int (modest_runtime_get_conf (),
402                                                   (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
403                                                   NULL);
404         /* We assume that we can only select messages of the
405            same folder and that we reply all of them from the
406            same account. In fact the interface currently only
407            allows single selection */
408         
409         /* Fill helpers */
410         rf_helper = g_slice_new0 (ReplyForwardHelper);
411         rf_helper->reply_forward_type = reply_forward_type;
412         rf_helper->action = action;
413
414         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
415         if (!rf_helper->account_name)
416                 rf_helper->account_name =
417                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
418
419         helper = g_slice_new0 (GetMsgAsyncHelper);
420         helper->window = win;
421         helper->func = reply_forward_func;
422         helper->iter = tny_list_create_iterator (header_list);
423         helper->user_data = rf_helper;
424
425         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
426                 TnyMsg *msg;
427                 msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
428                 if (!msg) {
429                         g_printerr ("modest: no message found\n");
430                         return;
431                 } else
432                         reply_forward_func (msg, helper);
433         } else {
434                 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
435                 folder = tny_header_get_folder (header);
436                 if (folder) {
437                         /* The callback will call it per each header */
438                         tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
439                         g_object_unref (G_OBJECT (folder));
440                 } else 
441                         g_printerr ("modest: no folder for header\n");
442                 
443                 /* Clean */
444                 g_object_unref (G_OBJECT (header));
445         }
446 }
447
448
449 void
450 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
451 {
452         g_return_if_fail (MODEST_IS_WINDOW(win));
453
454         reply_forward (ACTION_REPLY, win);
455 }
456
457 void
458 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
459 {
460         g_return_if_fail (MODEST_IS_WINDOW(win));
461
462         reply_forward (ACTION_FORWARD, win);
463 }
464
465 void
466 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
467 {
468         g_return_if_fail (MODEST_IS_WINDOW(win));
469
470         reply_forward (ACTION_REPLY_TO_ALL, win);
471 }
472
473 void 
474 modest_ui_actions_on_next (GtkAction *action, 
475                            ModestMainWindow *main_window)
476 {
477         GtkWidget *header_view;
478         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
479
480         header_view = modest_main_window_get_child_widget (main_window,
481                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
482         if (!header_view)
483                 return;
484         
485         modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
486 }
487
488 void 
489 modest_ui_actions_on_prev (GtkAction *action, 
490                            ModestMainWindow *main_window)
491 {
492         GtkWidget *header_view;
493         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
494
495         header_view = modest_main_window_get_child_widget (main_window,
496                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
497         if (!header_view)
498                 return;
499         
500         modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
501 }
502
503
504 void
505 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
506 {
507         gchar *account_name;
508         TnyAccount *tny_account;
509         //ModestTnySendQueue *send_queue;
510         ModestMailOperation *mail_op;
511         
512         account_name =
513                 g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
514         if (!account_name)
515                 account_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
516         if (!account_name) {
517                 g_printerr ("modest: cannot get account\n");
518                 return;
519         }
520         /* FIXME */
521 #if 0
522         tny_account = 
523                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
524                                                                      account_name,
525                                                                      TNY_ACCOUNT_TYPE_TRANSPORT);
526         if (!tny_account) {
527                 g_printerr ("modest: cannot get tny transport account for %s\n", account_name);
528                 return;
529         }
530
531         send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
532         if (!send_queue) {
533                 g_object_unref (G_OBJECT(tny_account));
534                 g_printerr ("modest: cannot get send queue for %s\n", account_name);
535                 return;
536         } 
537         modest_tny_send_queue_flush (send_queue);
538
539         g_object_unref (G_OBJECT(send_queue));
540         g_object_unref (G_OBJECT(tny_account));
541 #endif /*  0 */
542         tny_account = 
543                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
544                                                                      account_name,
545                                                                      TNY_ACCOUNT_TYPE_STORE);
546         if (!tny_account) {
547                 g_printerr ("modest: cannot get tny store account for %s\n", account_name);
548                 return;
549         }
550
551         mail_op = modest_mail_operation_new ();
552         modest_mail_operation_update_account (mail_op, TNY_STORE_ACCOUNT(tny_account));
553
554         g_object_unref (G_OBJECT(tny_account));
555         /* g_object_unref (G_OBJECT(mail_op)); FIXME: this is still in use... */
556 }
557
558
559
560 void
561 modest_ui_actions_toggle_view (GtkAction *action, ModestMainWindow *main_window)
562 {
563         ModestConf *conf;
564         GtkWidget *header_view;
565         
566         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
567
568         header_view = modest_main_window_get_child_widget (main_window,
569                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
570         if (!header_view)
571                 return;
572
573         conf = modest_runtime_get_conf ();
574         
575         /* what is saved/restored is depending on the style; thus; we save with
576          * old style, then update the style, and restore for this new style*/
577         modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
578         
579         if (modest_header_view_get_style
580             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
581                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
582                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
583         else
584                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
585                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
586
587         modest_widget_memory_restore (conf, G_OBJECT(header_view),
588                                       "header-view");
589 }
590
591
592
593 /*
594  * Marks a message as read and passes it to the msg preview widget
595  */
596 static void
597 read_msg_func (gpointer data, gpointer user_data)
598 {
599         TnyMsg *msg;
600         TnyHeader *header;
601         GetMsgAsyncHelper *helper;
602         TnyHeaderFlags header_flags;
603         GtkWidget *msg_preview;
604         
605         msg = TNY_MSG (data);
606         helper = (GetMsgAsyncHelper *) user_data;
607
608         msg_preview = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (helper->window),
609                                                            MODEST_WIDGET_TYPE_MSG_PREVIEW);
610         if (!msg_preview)
611                 return;
612         
613         header = TNY_HEADER (tny_iterator_get_current (helper->iter));
614         header_flags = tny_header_get_flags (header);
615         tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
616         g_object_unref (G_OBJECT (header));
617
618         /* Set message on msg view */
619         modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), msg);
620 }
621
622 /*
623  * This function is a generic handler for the tny_folder_get_msg_async
624  * call. It expects as user_data a #GetMsgAsyncHelper. This helper
625  * contains a user provided function that is called inside this
626  * method. This will allow us to use this callback in many different
627  * places. This callback performs the common actions for the
628  * get_msg_async call, more specific actions will be done by the user
629  * function
630  */
631 static void
632 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
633 {
634         GetMsgAsyncHelper *helper;
635
636         helper = (GetMsgAsyncHelper *) user_data;
637
638         if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
639                 modest_ui_actions_on_item_not_found (NULL,
640                                                      MODEST_ITEM_TYPE_MESSAGE,
641                                                      helper->window);
642                 return;
643         }
644
645         /* Call user function */
646         helper->func (msg, user_data);
647
648         /* Process next element (if exists) */
649         tny_iterator_next (helper->iter);
650         if (tny_iterator_is_done (helper->iter)) {
651                 TnyList *headers;
652                 headers = tny_iterator_get_list (helper->iter);
653                 /* Free resources */
654                 g_object_unref (G_OBJECT (headers));
655                 g_object_unref (G_OBJECT (helper->iter));
656                 g_slice_free (GetMsgAsyncHelper, helper);
657         } else {
658                 TnyHeader *header;
659                 header = TNY_HEADER (tny_iterator_get_current (helper->iter)); 
660                 tny_folder_get_msg_async (folder, header,                         
661                                           get_msg_cb, helper);
662                 g_object_unref (G_OBJECT(header));
663         }
664 }
665
666 void 
667 modest_ui_actions_on_header_selected (ModestHeaderView *folder_view, 
668                                       TnyHeader *header,
669                                       ModestMainWindow *main_window)
670 {
671         GtkWidget *msg_preview;
672         TnyFolder *folder;
673         GetMsgAsyncHelper *helper;
674         TnyList *list;
675
676         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
677         
678         msg_preview = modest_main_window_get_child_widget(main_window,
679                                                           MODEST_WIDGET_TYPE_MSG_PREVIEW);
680         if (!msg_preview)
681                 return;
682         
683         /* when there's no header, clear the msgview */
684         if (!header) {
685                 modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), NULL);
686                 return;
687         }
688
689         folder = tny_header_get_folder (TNY_HEADER(header));
690
691         /* Create list */
692         list = tny_simple_list_new ();
693         tny_list_prepend (list, G_OBJECT (header));
694
695         /* Fill helper data */
696         helper = g_slice_new0 (GetMsgAsyncHelper);
697         helper->window = MODEST_WINDOW (main_window);
698         helper->iter = tny_list_create_iterator (list);
699         helper->func = read_msg_func;
700
701         tny_folder_get_msg_async (TNY_FOLDER(folder),
702                                   header, get_msg_cb,
703                                   helper);
704
705         /* Frees */
706         g_object_unref (G_OBJECT (folder));
707 }
708
709
710
711 void 
712 modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, TnyHeader *header,
713                                        ModestMainWindow *main_window)
714 {
715         ModestWindow *win;
716         TnyFolder *folder = NULL;
717         TnyMsg    *msg    = NULL;
718         gchar *account    = NULL;
719         
720         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
721         
722         if (!header)
723                 return;
724
725         folder = tny_header_get_folder (header);
726         if (!folder) {
727                 g_printerr ("modest: cannot get folder for header\n");
728                 goto cleanup;
729         }
730
731         /* FIXME: make async?; check error  */
732         msg = tny_folder_get_msg (folder, header, NULL);
733         if (!msg) {
734                 g_printerr ("modest: cannot get msg for header\n");
735                 goto cleanup;
736         }
737
738         account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
739         if (!account)
740                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
741         
742         win = modest_msg_view_window_new (msg, account);
743         gtk_window_set_transient_for (GTK_WINDOW (win),
744                                       GTK_WINDOW (main_window));
745
746         gtk_widget_show_all (GTK_WIDGET(win));
747         
748 cleanup:
749         g_free (account);
750         
751         if (folder)
752                 g_object_unref (G_OBJECT (folder));
753         if (msg)
754                 g_object_unref (G_OBJECT (msg));
755 }
756
757 void 
758 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
759                                                TnyFolder *folder, 
760                                                gboolean selected,
761                                                ModestMainWindow *main_window)
762 {
763         gchar *txt;
764         ModestConf *conf;
765         GtkWidget *header_view;
766         
767         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
768
769         header_view = modest_main_window_get_child_widget(main_window,
770                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
771         if (!header_view)
772                 return;
773         
774         conf = modest_runtime_get_conf ();
775
776         if (!selected) { /* the folder was unselected; save it's settings  */
777                 modest_widget_memory_save (conf, G_OBJECT (header_view), "header-view");
778                 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
779                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
780         } else {  /* the folder was selected */
781                 if (folder) { /* folder may be NULL */
782                         guint num, unread;
783                         gchar *title;
784
785                         num    = tny_folder_get_all_count    (folder);
786                         unread = tny_folder_get_unread_count (folder);
787                         
788                         title = g_strdup_printf ("Modest: %s",
789                                                  tny_folder_get_name (folder));
790                         
791                         gtk_window_set_title (GTK_WINDOW(main_window), title);
792                         g_free (title);
793                         
794                         txt = g_strdup_printf (_("%d %s, %d unread"),
795                                                num, num==1 ? _("item") : _("items"), unread);           
796                         //gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
797                         g_free (txt);
798                 }
799                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), folder);
800                 modest_widget_memory_restore (conf, G_OBJECT(header_view),
801                                               "header-view");
802         }
803 }
804
805
806 /****************************************************/
807 /*
808  * below some stuff to clearup statusbar messages after 1,5 seconds....
809  */
810 static gboolean
811 progress_bar_clean (GtkWidget *bar)
812 {
813         if (GTK_IS_PROGRESS_BAR(bar)) {
814                 gtk_progress_bar_set_text     (GTK_PROGRESS_BAR(bar), "");
815                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0);
816         }
817         return FALSE;
818 }
819
820 static gboolean
821 statusbar_clean (GtkWidget *bar)
822 {
823         if (GTK_IS_STATUSBAR(bar))
824                 gtk_statusbar_push (GTK_STATUSBAR(bar), 0, "");
825         return FALSE;
826 }
827
828
829 static void
830 statusbar_push (ModestMainWindow *main_window, guint context_id, const gchar *msg)
831 {
832         if (!msg)
833                 return;
834
835         GtkWidget *progress_bar, *status_bar;
836
837         progress_bar = modest_main_window_get_child_widget (main_window,
838                                                             MODEST_WIDGET_TYPE_PROGRESS_BAR);
839         status_bar = modest_main_window_get_child_widget (main_window,
840                                                           MODEST_WIDGET_TYPE_STATUS_BAR);
841         if (progress_bar) {
842                 gtk_widget_show (progress_bar);
843                 g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar);
844         }
845         
846         if (status_bar) {
847                 gtk_widget_show (status_bar);
848                 gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
849                 g_timeout_add (2500, (GSourceFunc)statusbar_clean, status_bar);
850         }
851
852 }
853 /****************************************************************************/
854
855 void 
856 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
857                                      ModestWindow *win)
858 {
859         GtkWidget *dialog;
860         gchar *txt, *item;
861         gboolean online;
862
863         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
864         
865         if (g_main_depth > 0)   
866                 gdk_threads_enter ();
867         online = tny_device_is_online (modest_runtime_get_device());
868
869         if (online) {
870                 /* already online -- the item is simply not there... */
871                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
872                                                  GTK_DIALOG_MODAL,
873                                                  GTK_MESSAGE_WARNING,
874                                                  GTK_BUTTONS_OK,
875                                                  _("The %s you selected cannot be found"),
876                                                  item);
877                 gtk_dialog_run (GTK_DIALOG(dialog));
878         } else {
879                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
880                                                       GTK_WINDOW (win),
881                                                       GTK_DIALOG_MODAL,
882                                                       GTK_STOCK_CANCEL,
883                                                       GTK_RESPONSE_REJECT,
884                                                       GTK_STOCK_OK,
885                                                       GTK_RESPONSE_ACCEPT,
886                                                       NULL);
887                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
888                                          "Do you want to get online?"), item);
889                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
890                                     gtk_label_new (txt), FALSE, FALSE, 0);
891                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
892                 g_free (txt);
893
894                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
895                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
896                         tny_device_force_online (modest_runtime_get_device());
897                 }
898         }
899         gtk_widget_destroy (dialog);
900         if (g_main_depth > 0)   
901                 gdk_threads_leave ();
902 }
903
904
905
906 void
907 modest_ui_actions_on_header_status_update (ModestHeaderView *header_view, 
908                                             const gchar *msg, gint num, 
909                                             gint total,  ModestMainWindow *main_window)
910 {
911         char* txt;
912         GtkWidget *progress_bar;
913
914         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
915
916         progress_bar = modest_main_window_get_child_widget (main_window, 
917                                                             MODEST_WIDGET_TYPE_PROGRESS_BAR);   
918         if (!progress_bar)
919                 return;
920         
921         if (total != 0)
922                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
923                                                (gdouble)num/(gdouble)total);
924         else
925                 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
926
927         txt = g_strdup_printf (_("Downloading %d of %d"), num, total);
928         gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt);
929         g_free (txt);
930         
931         statusbar_push (main_window, 0, msg);
932 }
933
934
935 void
936 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
937                                      ModestWindow *win)
938 {
939         g_message (__FUNCTION__);
940 }       
941
942
943 void
944 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
945                                         ModestWindow *win)
946 {
947         g_message (__FUNCTION__);
948 }
949
950 void
951 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, int index,
952                                              ModestWindow *win)
953 {
954         g_message (__FUNCTION__);
955         
956 }
957
958 void
959 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
960                                           ModestRecptView *recpt_view,
961                                           ModestWindow *win)
962 {
963         gint start, end;
964         gchar *utf_start, *utf_end;
965         gchar *full_string = NULL;
966         gchar *substring;
967
968         gtk_label_get_selection_bounds (GTK_LABEL (recpt_view), &start, &end);
969         full_string = (gchar *) gtk_label_get_text (GTK_LABEL (recpt_view));
970         utf_start = g_utf8_offset_to_pointer (full_string, start);
971         utf_end = g_utf8_offset_to_pointer (full_string, end);
972         substring = g_strndup (utf_start, utf_end - utf_start);
973         g_message ("%s %s", __FUNCTION__, substring);
974
975         g_free (substring);
976         
977 }
978
979 void
980 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
981 {
982         TnyTransportAccount *transport_account;
983         ModestMailOperation *mail_operation;
984         MsgData *data;
985         gchar *account_name, *from;
986         ModestAccountMgr *account_mgr;
987
988         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
989         
990         data = modest_msg_edit_window_get_msg_data (edit_window);
991
992         /* FIXME: Code added just for testing. The final version will
993            use the send queue provided by tinymail and some
994            classifier */
995         account_mgr = modest_runtime_get_account_mgr();
996         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
997         if (!account_name) 
998                 account_name = modest_account_mgr_get_default_account (account_mgr);
999         if (!account_name) {
1000                 g_printerr ("modest: no account found\n");
1001                 modest_msg_edit_window_free_msg_data (edit_window, data);
1002                 return;
1003         }
1004         transport_account =
1005                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1006                                       (modest_runtime_get_account_store(),
1007                                        account_name,
1008                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1009         if (!transport_account) {
1010                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1011                 g_free (account_name);
1012                 modest_msg_edit_window_free_msg_data (edit_window, data);
1013                 return;
1014         }
1015         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1016                 
1017         mail_operation = modest_mail_operation_new ();
1018         modest_mail_operation_send_new_mail (mail_operation,
1019                                              transport_account,
1020                                              from,
1021                                              data->to, 
1022                                              data->cc, 
1023                                              data->bcc,
1024                                              data->subject, 
1025                                              data->body, 
1026                                              NULL);
1027         /* Frees */
1028         g_free (from);
1029         g_free (account_name);
1030         g_object_unref (G_OBJECT (mail_operation));
1031         g_object_unref (G_OBJECT (transport_account));
1032
1033         modest_msg_edit_window_free_msg_data (edit_window, data);
1034
1035         /* Save settings and close the window */
1036         /* save_settings (edit_window) */
1037         gtk_widget_destroy (GTK_WIDGET (edit_window));
1038 }
1039
1040 /*
1041  * Shows a dialog with an entry that asks for some text. The returned
1042  * value must be freed by the caller. The dialog window title will be
1043  * set to @title.
1044  */
1045 static gchar *
1046 ask_for_folder_name (GtkWindow *parent_window,
1047                      const gchar *title)
1048 {
1049         GtkWidget *dialog, *entry;
1050         gchar *folder_name = NULL;
1051
1052         /* Ask for folder name */
1053         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1054                                               parent_window,
1055                                               GTK_DIALOG_MODAL,
1056                                               GTK_STOCK_CANCEL,
1057                                               GTK_RESPONSE_REJECT,
1058                                               GTK_STOCK_OK,
1059                                               GTK_RESPONSE_ACCEPT,
1060                                               NULL);
1061         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1062                             gtk_label_new(title),
1063                             FALSE, FALSE, 0);
1064                 
1065         entry = gtk_entry_new_with_max_length (40);
1066         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1067                             entry,
1068                             TRUE, FALSE, 0);    
1069         
1070         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1071         
1072         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1073                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1074
1075         gtk_widget_destroy (dialog);
1076
1077         return folder_name;
1078 }
1079
1080 void 
1081 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1082 {
1083         TnyFolder *parent_folder;
1084         GtkWidget *folder_view;
1085         
1086         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1087
1088         folder_view = modest_main_window_get_child_widget (main_window,
1089                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1090         if (!folder_view)
1091                 return;
1092
1093         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1094         
1095         if (parent_folder) {
1096                 gchar *folder_name;
1097
1098                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1099                                                    _("Please enter a name for the new folder"));
1100
1101                 if (folder_name != NULL && strlen (folder_name) > 0) {
1102                         TnyFolder *new_folder;
1103                         ModestMailOperation *mail_op;
1104
1105                         mail_op = modest_mail_operation_new ();
1106                         new_folder = modest_mail_operation_create_folder (mail_op,
1107                                                                           TNY_FOLDER_STORE (parent_folder),
1108                                                                           (const gchar *) folder_name);
1109                         if (new_folder) {
1110                                 g_object_unref (new_folder);
1111                         } else {
1112                                 const GError *error;
1113                                 error = modest_mail_operation_get_error (mail_op);
1114                                 if (error)
1115                                         g_warning ("Error adding a subfolder: %s\n", error->message);
1116                         }
1117                         g_object_unref (mail_op);
1118                 }
1119                 g_object_unref (parent_folder);
1120         }
1121 }
1122
1123 void 
1124 modest_ui_actions_on_rename_folder (GtkAction *action,
1125                                      ModestMainWindow *main_window)
1126 {
1127         TnyFolder *folder;
1128         GtkWidget *folder_view;
1129         
1130         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1131
1132         folder_view = modest_main_window_get_child_widget (main_window,
1133                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1134         if (!folder_view)
1135                 return;
1136         
1137         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1138         
1139         if (folder) {
1140                 gchar *folder_name;
1141                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1142                                                    _("Please enter a new name for the folder"));
1143
1144                 if (folder_name != NULL && strlen (folder_name) > 0) {
1145                         ModestMailOperation *mail_op;
1146                         const GError *error;
1147
1148                         mail_op = modest_mail_operation_new ();
1149                         modest_mail_operation_rename_folder (mail_op,
1150                                                              folder,
1151                                                              (const gchar *) folder_name);
1152
1153                         error = modest_mail_operation_get_error (mail_op);
1154                         if (error)
1155                                 /* TODO: notify error ? */
1156                                 g_warning ("Could not rename a folder: %s\n", error->message);
1157
1158                         g_object_unref (mail_op);
1159                 }
1160                 g_object_unref (folder);
1161         }
1162 }
1163
1164 static void
1165 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1166 {
1167         TnyFolder *folder;
1168         ModestMailOperation *mail_op;
1169         GtkWidget *folder_view;
1170         const GError *error;
1171         
1172         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1173
1174         folder_view = modest_main_window_get_child_widget (main_window,
1175                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1176         if (!folder_view)
1177                 return;
1178
1179         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1180         
1181         mail_op = modest_mail_operation_new ();
1182         modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1183
1184         error = modest_mail_operation_get_error (mail_op);
1185         if (error)
1186                 g_warning ("%s\n", error->message);
1187
1188         g_object_unref (G_OBJECT (mail_op));
1189         g_object_unref (G_OBJECT (folder));
1190 }
1191
1192 void 
1193 modest_ui_actions_on_delete_folder (GtkAction *action,
1194                                      ModestMainWindow *main_window)
1195 {
1196         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1197
1198         delete_folder (main_window, FALSE);
1199 }
1200
1201 void 
1202 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1203 {
1204         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1205         
1206         delete_folder (main_window, TRUE);
1207 }
1208
1209 void
1210 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1211                                          const gchar* account_name,
1212                                          gchar **password, 
1213                                          gboolean *cancel, 
1214                                          gboolean *remember,
1215                                          ModestMainWindow *main_window)
1216 {
1217         gchar *txt;
1218         GtkWidget *dialog, *entry, *remember_pass_check;
1219
1220         dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1221                                               NULL,
1222                                               GTK_DIALOG_MODAL,
1223                                               GTK_STOCK_CANCEL,
1224                                               GTK_RESPONSE_REJECT,
1225                                               GTK_STOCK_OK,
1226                                               GTK_RESPONSE_ACCEPT,
1227                                               NULL);
1228         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1229         
1230         txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1231         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1232                             FALSE, FALSE, 0);
1233         g_free (txt);
1234
1235         entry = gtk_entry_new_with_max_length (40);
1236         gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1237         gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1238         
1239         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1240                             TRUE, FALSE, 0);    
1241
1242         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1243         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1244                             TRUE, FALSE, 0);
1245
1246         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1247         
1248         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1249                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1250                 *cancel   = FALSE;
1251         } else {
1252                 *password = NULL;
1253                 *cancel   = TRUE;
1254         }
1255
1256         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1257                 *remember = TRUE;
1258         else
1259                 *remember = FALSE;
1260
1261         gtk_widget_destroy (dialog);
1262 }