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