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