* modest-tny-send-queue:
[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         TnyDevice *device;
417         TnyAccountStore *account_store;
418         gchar *account_name;
419         TnyAccount *tny_account;
420         ModestTnySendQueue *send_queue;
421         
422         /* Get device. Do not ask the platform factory for it, because
423            it returns always a new one */
424         account_store = TNY_ACCOUNT_STORE (modest_runtime_get_account_store ());
425         device = tny_account_store_get_device (account_store);
426                 
427         account_name =
428                 g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
429         if (!account_name)
430                 account_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
431         if (!account_name) {
432                 g_printerr ("modest: cannot get account\n");
433                 return;
434         }
435
436         tny_account = 
437                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
438                                                                      account_name, TNY_ACCOUNT_TYPE_TRANSPORT);
439         if (!tny_account) {
440                 g_printerr ("modest: cannot get tny transport account\n");
441                 return;
442         }
443
444         send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
445         modest_tny_send_queue_flush (send_queue);
446
447         g_object_unref (G_OBJECT(send_queue));
448         g_object_unref (G_OBJECT(tny_account));
449 }
450
451
452
453 void
454 modest_ui_actions_toggle_view (GtkWidget *widget, ModestMainWindow *main_window)
455 {
456         ModestConf *conf;
457         GtkWidget *header_view;
458         
459         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
460
461         header_view = modest_main_window_get_child_widget (main_window,
462                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
463         if (!header_view)
464                 return;
465
466         conf = modest_runtime_get_conf ();
467         
468         /* what is saved/restored is depending on the style; thus; we save with
469          * old style, then update the style, and restore for this new style*/
470         modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
471         
472         if (modest_header_view_get_style
473             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
474                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
475                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
476         else
477                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
478                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
479
480         modest_widget_memory_restore (conf, G_OBJECT(header_view),
481                                       "header-view");
482 }
483
484
485
486 /*
487  * Marks a message as read and passes it to the msg preview widget
488  */
489 static void
490 read_msg_func (gpointer data, gpointer user_data)
491 {
492         TnyMsg *msg;
493         TnyHeader *header;
494         GetMsgAsyncHelper *helper;
495         TnyHeaderFlags header_flags;
496         GtkWidget *msg_preview;
497         
498         msg = TNY_MSG (data);
499         helper = (GetMsgAsyncHelper *) user_data;
500
501         msg_preview = modest_main_window_get_child_widget (helper->main_window,
502                                                            MODEST_WIDGET_TYPE_MSG_PREVIEW);
503         if (!msg_preview)
504                 return;
505         
506         /* mark message as seen; _set_flags crashes, bug in tinymail? */
507         header = TNY_HEADER (tny_iterator_get_current (helper->iter));
508         header_flags = tny_header_get_flags (header);
509         tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
510         g_object_unref (G_OBJECT (header));
511
512         /* Set message on msg view */
513         modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), msg);
514 }
515
516 /*
517  * This function is a generic handler for the tny_folder_get_msg_async
518  * call. It expects as user_data a #GetMsgAsyncHelper. This helper
519  * contains a user provided function that is called inside this
520  * method. This will allow us to use this callback in many different
521  * places. This callback performs the common actions for the
522  * get_msg_async call, more specific actions will be done by the user
523  * function
524  */
525 static void
526 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
527 {
528         GetMsgAsyncHelper *helper;
529
530         helper = (GetMsgAsyncHelper *) user_data;
531
532         if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
533                 GtkWidget *header_view =
534                         modest_main_window_get_child_widget(helper->main_window,
535                                                             MODEST_WIDGET_TYPE_HEADER_VIEW);
536                 if (header_view)
537                         modest_ui_actions_on_item_not_found (MODEST_HEADER_VIEW(header_view),
538                                                              MODEST_ITEM_TYPE_MESSAGE,
539                                                              MODEST_WINDOW(helper->main_window));
540                 return;
541         }
542
543         /* Call user function */
544         helper->func (msg, user_data);
545
546         /* Process next element (if exists) */
547         tny_iterator_next (helper->iter);
548         if (tny_iterator_is_done (helper->iter)) {
549                 TnyList *headers;
550                 headers = tny_iterator_get_list (helper->iter);
551                 /* Free resources */
552                 g_object_unref (G_OBJECT (headers));
553                 g_object_unref (G_OBJECT (helper->iter));
554                 g_slice_free (GetMsgAsyncHelper, helper);
555         } else {
556                 TnyHeader *header;
557                 header = TNY_HEADER (tny_iterator_get_current (helper->iter)); 
558                 tny_folder_get_msg_async (folder, header,                         
559                                           get_msg_cb, helper);
560                 g_object_unref (G_OBJECT(header));
561         }
562 }
563
564 void 
565 modest_ui_actions_on_header_selected (ModestHeaderView *folder_view, 
566                                       TnyHeader *header,
567                                       ModestMainWindow *main_window)
568 {
569         GtkWidget *msg_preview;
570         TnyFolder *folder;
571         GetMsgAsyncHelper *helper;
572         TnyList *list;
573
574         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
575         
576         msg_preview = modest_main_window_get_child_widget(main_window,
577                                                           MODEST_WIDGET_TYPE_MSG_PREVIEW);
578         if (!msg_preview)
579                 return;
580         
581         /* when there's no header, clear the msgview */
582         if (!header) {
583                 modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), NULL);
584                 return;
585         }
586
587         folder = tny_header_get_folder (TNY_HEADER(header));
588
589         /* Create list */
590         list = tny_simple_list_new ();
591         tny_list_prepend (list, G_OBJECT (header));
592
593         /* Fill helper data */
594         helper = g_slice_new0 (GetMsgAsyncHelper);
595         helper->main_window = main_window;
596         helper->iter = tny_list_create_iterator (list);
597         helper->func = read_msg_func;
598
599         tny_folder_get_msg_async (TNY_FOLDER(folder),
600                                   header, get_msg_cb,
601                                   helper);
602
603         /* Frees */
604         g_object_unref (G_OBJECT (folder));
605 }
606
607
608
609 void 
610 modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, TnyHeader *header,
611                                        ModestMainWindow *main_window)
612 {
613         ModestWindow *win;
614         TnyFolder *folder = NULL;
615         TnyMsg    *msg    = NULL;
616         gchar *account    = NULL;
617         
618         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
619         
620         if (!header)
621                 return;
622
623         folder = tny_header_get_folder (header);
624         if (!folder) {
625                 g_printerr ("modest: cannot get folder for header\n");
626                 goto cleanup;
627         }
628
629         /* FIXME: make async?; check error  */
630         msg = tny_folder_get_msg (folder, header, NULL);
631         if (!msg) {
632                 g_printerr ("modest: cannot get msg for header\n");
633                 goto cleanup;
634         }
635
636         account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
637         if (!account)
638                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
639         
640         win = modest_msg_view_window_new (msg, account);
641         gtk_window_set_transient_for (GTK_WINDOW (win),
642                                       GTK_WINDOW (main_window));
643
644         gtk_widget_show_all (GTK_WIDGET(win));
645         
646 cleanup:
647         g_free (account);
648         
649         if (folder)
650                 g_object_unref (G_OBJECT (folder));
651         if (msg)
652                 g_object_unref (G_OBJECT (folder));
653 }
654
655
656
657
658
659 void 
660 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
661                                                TnyFolder *folder, 
662                                                gboolean selected,
663                                                ModestMainWindow *main_window)
664 {
665 //      GtkLabel *folder_info_label;
666         gchar *txt;     
667         ModestConf *conf;
668         GtkWidget *header_view;
669         
670 /*      folder_info_label =  */
671 /*              GTK_LABEL (modest_widget_factory_get_folder_info_label */
672 /*                         (modest_runtime_get_widget_factory())); */
673
674 /*      if (!folder) { */
675 /*              gtk_label_set_label (GTK_LABEL(folder_info_label), ""); */
676 /*              return; */
677 /*      } */
678         
679         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
680
681         header_view = modest_main_window_get_child_widget(main_window,
682                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
683         if (!header_view)
684                 return;
685         
686         conf = modest_runtime_get_conf ();
687
688         if (!selected) { /* the folder was unselected; save it's settings  */
689                 modest_widget_memory_save (conf, G_OBJECT (header_view), "header-view");
690                 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
691                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
692         } else {  /* the folder was selected */
693                 if (folder) { /* folder may be NULL */
694                         guint num, unread;
695                         gchar *title;
696
697                         num    = tny_folder_get_all_count    (folder);
698                         unread = tny_folder_get_unread_count (folder);
699                         
700                         title = g_strdup_printf ("Modest: %s",
701                                                  tny_folder_get_name (folder));
702                         
703                         gtk_window_set_title (GTK_WINDOW(main_window), title);
704                         g_free (title);
705                         
706                         txt = g_strdup_printf (_("%d %s, %d unread"),
707                                                num, num==1 ? _("item") : _("items"), unread);           
708                         //gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
709                         g_free (txt);
710                 }
711                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), folder);
712                 modest_widget_memory_restore (conf, G_OBJECT(header_view),
713                                               "header-view");
714         }
715 }
716
717
718 /****************************************************/
719 /*
720  * below some stuff to clearup statusbar messages after 1,5 seconds....
721  */
722 static gboolean
723 progress_bar_clean (GtkWidget *bar)
724 {
725         if (GTK_IS_PROGRESS_BAR(bar)) {
726                 gtk_progress_bar_set_text     (GTK_PROGRESS_BAR(bar), "");
727                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0);
728         }
729         return FALSE;
730 }
731
732 static gboolean
733 statusbar_clean (GtkWidget *bar)
734 {
735         if (GTK_IS_STATUSBAR(bar))
736                 gtk_statusbar_push (GTK_STATUSBAR(bar), 0, "");
737         return FALSE;
738 }
739
740
741 static void
742 statusbar_push (ModestMainWindow *main_window, guint context_id, const gchar *msg)
743 {
744         if (!msg)
745                 return;
746
747         GtkWidget *progress_bar, *status_bar;
748
749         progress_bar = modest_main_window_get_child_widget (main_window,
750                                                             MODEST_WIDGET_TYPE_PROGRESS_BAR);
751         status_bar = modest_main_window_get_child_widget (main_window,
752                                                           MODEST_WIDGET_TYPE_STATUS_BAR);
753         if (progress_bar) {
754                 gtk_widget_show (progress_bar);
755                 g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar);
756         }
757         
758         if (status_bar) {
759                 gtk_widget_show (status_bar);
760                 gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
761                 g_timeout_add (1500, (GSourceFunc)statusbar_clean, status_bar);
762         }
763
764 }
765 /****************************************************************************/
766
767 void 
768 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
769                                      ModestWindow *win)
770 {
771         GtkWidget *dialog;
772         gchar *txt, *item;
773         gboolean online;
774         TnyDevice *device;
775         TnyAccountStore *account_store;
776
777         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
778         
779         /* Get device. Do not ask the platform factory for it, because
780            it returns always a new one */
781         account_store = TNY_ACCOUNT_STORE (modest_runtime_get_account_store ());
782         device = tny_account_store_get_device (account_store);
783
784         if (g_main_depth > 0)   
785                 gdk_threads_enter ();
786         online = tny_device_is_online (device);
787
788         if (online) {
789                 /* already online -- the item is simply not there... */
790                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
791                                                  GTK_DIALOG_MODAL,
792                                                  GTK_MESSAGE_WARNING,
793                                                  GTK_BUTTONS_OK,
794                                                  _("The %s you selected cannot be found"),
795                                                  item);
796                 gtk_dialog_run (GTK_DIALOG(dialog));
797         } else {
798                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
799                                                       GTK_WINDOW (win),
800                                                       GTK_DIALOG_MODAL,
801                                                       GTK_STOCK_CANCEL,
802                                                       GTK_RESPONSE_REJECT,
803                                                       GTK_STOCK_OK,
804                                                       GTK_RESPONSE_ACCEPT,
805                                                       NULL);
806                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
807                                          "Do you want to get online?"), item);
808                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
809                                     gtk_label_new (txt), FALSE, FALSE, 0);
810                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
811                 g_free (txt);
812
813                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
814                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
815                         tny_device_force_online (device);
816                 }
817         }
818         gtk_widget_destroy (dialog);
819         if (g_main_depth > 0)   
820                 gdk_threads_leave ();
821 }
822
823
824
825 void
826 modest_ui_actions_on_header_status_update (ModestHeaderView *header_view, 
827                                             const gchar *msg, gint num, 
828                                             gint total,  ModestMainWindow *main_window)
829 {
830         char* txt;
831         GtkWidget *progress_bar;
832
833         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
834
835         progress_bar = modest_main_window_get_child_widget (main_window, 
836                                                             MODEST_WIDGET_TYPE_PROGRESS_BAR);   
837         if (!progress_bar)
838                 return;
839         
840         if (total != 0)
841                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
842                                                (gdouble)num/(gdouble)total);
843         else
844                 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
845
846         txt = g_strdup_printf (_("Downloading %d of %d"), num, total);
847         gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt);
848         g_free (txt);
849         
850         statusbar_push (main_window, 0, msg);
851 }
852
853
854 void
855 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
856                                      ModestWindow *win)
857 {
858         g_message (__FUNCTION__);
859 }       
860
861
862 void
863 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
864                                         ModestWindow *win)
865 {
866         g_message (__FUNCTION__);
867 }
868
869 void
870 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, int index,
871                                              ModestWindow *win)
872 {
873         g_message (__FUNCTION__);
874         
875 }
876
877 void
878 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
879 {
880         TnyTransportAccount *transport_account;
881         ModestMailOperation *mail_operation;
882         MsgData *data;
883         gchar *account_name, *from;
884         ModestAccountMgr *account_mgr;
885
886         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
887         
888         data = modest_msg_edit_window_get_msg_data (edit_window);
889
890         /* FIXME: Code added just for testing. The final version will
891            use the send queue provided by tinymail and some
892            classifier */
893         account_mgr = modest_runtime_get_account_mgr();
894         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
895         if (!account_name) 
896                 account_name = modest_account_mgr_get_default_account (account_mgr);
897         if (!account_name) {
898                 g_printerr ("modest: no account found\n");
899                 modest_msg_edit_window_free_msg_data (edit_window, data);
900                 return;
901         }
902         transport_account =
903                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
904                                       (modest_runtime_get_account_store(),
905                                        account_name,
906                                        TNY_ACCOUNT_TYPE_TRANSPORT));
907         if (!transport_account) {
908                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
909                 g_free (account_name);
910                 modest_msg_edit_window_free_msg_data (edit_window, data);
911                 return;
912         }
913         from = modest_account_mgr_get_from_string (account_mgr, account_name);
914                 
915         mail_operation = modest_mail_operation_new ();
916         modest_mail_operation_send_new_mail (mail_operation,
917                                              transport_account,
918                                              from,
919                                              data->to, 
920                                              data->cc, 
921                                              data->bcc,
922                                              data->subject, 
923                                              data->body, 
924                                              NULL);
925         /* Frees */
926         g_free (from);
927         g_free (account_name);
928         g_object_unref (G_OBJECT (mail_operation));
929         g_object_unref (G_OBJECT (transport_account));
930
931         modest_msg_edit_window_free_msg_data (edit_window, data);
932
933         /* Save settings and close the window */
934         /* save_settings (edit_window) */
935         gtk_widget_destroy (GTK_WIDGET (edit_window));
936 }
937
938 /*
939  * Shows a dialog with an entry that asks for some text. The returned
940  * value must be freed by the caller. The dialog window title will be
941  * set to @title.
942  */
943 static gchar *
944 ask_for_folder_name (GtkWindow *parent_window,
945                      const gchar *title)
946 {
947         GtkWidget *dialog, *entry;
948         gchar *folder_name = NULL;
949
950         /* Ask for folder name */
951         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
952                                               parent_window,
953                                               GTK_DIALOG_MODAL,
954                                               GTK_STOCK_CANCEL,
955                                               GTK_RESPONSE_REJECT,
956                                               GTK_STOCK_OK,
957                                               GTK_RESPONSE_ACCEPT,
958                                               NULL);
959         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
960                             gtk_label_new(title),
961                             FALSE, FALSE, 0);
962                 
963         entry = gtk_entry_new_with_max_length (40);
964         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
965                             entry,
966                             TRUE, FALSE, 0);    
967         
968         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
969         
970         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
971                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
972
973         gtk_widget_destroy (dialog);
974
975         return folder_name;
976 }
977
978 void 
979 modest_ui_actions_on_new_folder (GtkWidget *widget, ModestMainWindow *main_window)
980 {
981         TnyFolder *parent_folder;
982         GtkWidget *folder_view;
983         
984         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
985
986         folder_view = modest_main_window_get_child_widget (main_window,
987                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
988         if (!folder_view)
989                 return;
990
991         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
992         
993         if (parent_folder) {
994                 gchar *folder_name;
995
996                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
997                                                    _("Please enter a name for the new folder"));
998
999                 if (folder_name != NULL && strlen (folder_name) > 0) {
1000                         TnyFolder *new_folder;
1001                         ModestMailOperation *mail_op;
1002
1003                         mail_op = modest_mail_operation_new ();
1004                         new_folder = modest_mail_operation_create_folder (mail_op,
1005                                                                           TNY_FOLDER_STORE (parent_folder),
1006                                                                           (const gchar *) folder_name);
1007                         if (new_folder) {
1008                                 /* TODO: tinymail should do this. 
1009                                    Update view */
1010                                 modest_folder_view_add_subfolder (MODEST_FOLDER_VIEW(folder_view),
1011                                                                   new_folder);
1012
1013                                 /* Free new folder */
1014                                 g_object_unref (new_folder);
1015                         }
1016                         g_object_unref (mail_op);
1017                 }
1018                 g_object_unref (parent_folder);
1019         }
1020 }
1021
1022 void 
1023 modest_ui_actions_on_rename_folder (GtkWidget *widget,
1024                                      ModestMainWindow *main_window)
1025 {
1026         TnyFolder *folder;
1027         GtkWidget *folder_view;
1028         
1029         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1030
1031         folder_view = modest_main_window_get_child_widget (main_window,
1032                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1033         if (!folder_view)
1034                 return;
1035         
1036         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1037         
1038         if (folder) {
1039                 gchar *folder_name;
1040                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1041                                                    _("Please enter a new name for the folder"));
1042
1043                 if (folder_name != NULL && strlen (folder_name) > 0) {
1044                         ModestMailOperation *mail_op;
1045                         const GError *error;
1046
1047                         mail_op = modest_mail_operation_new ();
1048                         modest_mail_operation_rename_folder (mail_op,
1049                                                              folder,
1050                                                              (const gchar *) folder_name);
1051
1052                         error = modest_mail_operation_get_error (mail_op);
1053                         if (!error)
1054                                 /* TODO: tinymail should do this. 
1055                                    Update view */
1056                                 modest_folder_view_rename (MODEST_FOLDER_VIEW(folder_view));
1057
1058                         /* TODO: else ? notify error ? */
1059
1060                         g_object_unref (mail_op);
1061                 }
1062                 g_object_unref (folder);
1063         }
1064 }
1065
1066 static void
1067 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1068 {
1069         TnyFolder *folder;
1070         ModestMailOperation *mail_op;
1071         GtkWidget *folder_view;
1072         
1073         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1074
1075         folder_view = modest_main_window_get_child_widget (main_window,
1076                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1077         if (!folder_view)
1078                 return;
1079
1080         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1081         
1082         mail_op = modest_mail_operation_new ();
1083         modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1084         g_object_unref (mail_op);
1085 }
1086
1087 void 
1088 modest_ui_actions_on_delete_folder (GtkWidget *widget,
1089                                      ModestMainWindow *main_window)
1090 {
1091         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1092
1093         delete_folder (main_window, FALSE);
1094 }
1095
1096 void 
1097 modest_ui_actions_on_move_folder_to_trash_folder (GtkWidget *widget, ModestMainWindow *main_window)
1098 {
1099         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1100         
1101         delete_folder (main_window, TRUE);
1102 }
1103
1104 void
1105 modest_ui_actions_on_accounts_reloaded (TnyAccountStore *store, gpointer user_data)
1106 {
1107         /* FIXME */
1108         /* ModestFolderView *folder_view; */
1109         
1110 /*      folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory()); */
1111 /*      modest_folder_view_update_model (folder_view, store); */
1112 }
1113
1114 void 
1115 modest_ui_actions_on_folder_moved (ModestFolderView *folder_view,  TnyFolder *folder, 
1116                                     TnyFolderStore *parent,  gboolean *done,
1117                                     gpointer user_data)
1118 {
1119         ModestMailOperation *mail_op;
1120         const GError *error;
1121
1122         *done = TRUE;
1123
1124         /* Try to move the folder */    
1125         mail_op = modest_mail_operation_new ();
1126         modest_mail_operation_move_folder (mail_op, folder, parent);
1127
1128         error = modest_mail_operation_get_error (mail_op);
1129         if (error)
1130                 *done = FALSE;
1131
1132         g_object_unref (G_OBJECT (mail_op));
1133 }
1134
1135
1136
1137 void
1138 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1139                                          const gchar* account_name,
1140                                          gchar **password, 
1141                                          gboolean *cancel, 
1142                                          gboolean *remember,
1143                                          ModestMainWindow *main_window)
1144 {
1145         gchar *txt;
1146         GtkWidget *dialog, *entry, *remember_pass_check;
1147
1148         dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1149                                               NULL,
1150                                               GTK_DIALOG_MODAL,
1151                                               GTK_STOCK_CANCEL,
1152                                               GTK_RESPONSE_REJECT,
1153                                               GTK_STOCK_OK,
1154                                               GTK_RESPONSE_ACCEPT,
1155                                               NULL);
1156         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1157         
1158         txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1159         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1160                             FALSE, FALSE, 0);
1161         g_free (txt);
1162
1163         entry = gtk_entry_new_with_max_length (40);
1164         gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1165         gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1166         
1167         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1168                             TRUE, FALSE, 0);    
1169
1170         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1171         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1172                             TRUE, FALSE, 0);
1173
1174         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1175         
1176         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1177                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1178                 *cancel   = FALSE;
1179         } else {
1180                 *password = NULL;
1181                 *cancel   = TRUE;
1182         }
1183
1184         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1185                 *remember = TRUE;
1186         else
1187                 *remember = FALSE;
1188
1189         gtk_widget_destroy (dialog);
1190 }