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