cefe3fb11513a3b445921ab72009d2d7116636bd
[modest] / src / maemo / modest-edit-msg-window.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 #include <glib/gi18n.h>
30 #include <tny-account-store.h>
31 #include <widgets/modest-edit-msg-window.h>
32 #include <hildon-widgets/hildon-window.h>
33 #include <widgets/modest-toolbar.h>
34 #include "modest-widget-memory.h"
35 #include "modest-mail-operation.h"
36 #include "modest-tny-platform-factory.h"
37 #include "modest-tny-msg-actions.h"
38 #include <tny-simple-list.h>
39 #include <string.h>
40
41
42 static void  modest_edit_msg_window_class_init   (ModestEditMsgWindowClass *klass);
43 static void  modest_edit_msg_window_init         (ModestEditMsgWindow *obj);
44 static void  modest_edit_msg_window_finalize     (GObject *obj);
45
46 /* list my signals */
47 enum {
48         /* MY_SIGNAL_1, */
49         /* MY_SIGNAL_2, */
50         LAST_SIGNAL
51 };
52
53 typedef struct _ModestEditMsgWindowPrivate ModestEditMsgWindowPrivate;
54 struct _ModestEditMsgWindowPrivate {
55
56         ModestWidgetFactory *factory;
57         TnyPlatformFactory *fact;
58         
59         GtkWidget      *toolbar, *menubar;
60         GtkWidget      *msg_body;
61         GtkWidget      *from_field, *to_field, *cc_field, *bcc_field,
62                        *subject_field;
63         GtkUIManager   *ui_manager;
64 };
65 #define MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
66                                                     MODEST_TYPE_EDIT_MSG_WINDOW, \
67                                                     ModestEditMsgWindowPrivate))
68 /* globals */
69 static GtkWindowClass *parent_class = NULL;
70
71 /* uncomment the following if you have defined any signals */
72 /* static guint signals[LAST_SIGNAL] = {0}; */
73
74 GType
75 modest_edit_msg_window_get_type (void)
76 {
77         static GType my_type = 0;
78         if (!my_type) {
79                 static const GTypeInfo my_info = {
80                         sizeof(ModestEditMsgWindowClass),
81                         NULL,           /* base init */
82                         NULL,           /* base finalize */
83                         (GClassInitFunc) modest_edit_msg_window_class_init,
84                         NULL,           /* class finalize */
85                         NULL,           /* class data */
86                         sizeof(ModestEditMsgWindow),
87                         1,              /* n_preallocs */
88                         (GInstanceInitFunc) modest_edit_msg_window_init,
89                         NULL
90                 };
91                 my_type = g_type_register_static (HILDON_TYPE_WINDOW,
92                                                   "ModestEditMsgWindow",
93                                                   &my_info, 0);
94         }
95         return my_type;
96 }
97
98 static void
99 modest_edit_msg_window_class_init (ModestEditMsgWindowClass *klass)
100 {
101         GObjectClass *gobject_class;
102         gobject_class = (GObjectClass*) klass;
103
104         parent_class            = g_type_class_peek_parent (klass);
105         gobject_class->finalize = modest_edit_msg_window_finalize;
106
107         g_type_class_add_private (gobject_class, sizeof(ModestEditMsgWindowPrivate));
108
109         /* signal definitions go here, e.g.: */
110 /*      signals[MY_SIGNAL_1] = */
111 /*              g_signal_new ("my_signal_1",....); */
112 /*      signals[MY_SIGNAL_2] = */
113 /*              g_signal_new ("my_signal_2",....); */
114 /*      etc. */
115 }
116
117 static void
118 modest_edit_msg_window_init (ModestEditMsgWindow *obj)
119 {
120         ModestEditMsgWindowPrivate *priv;
121         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
122
123         priv->fact = modest_tny_platform_factory_get_instance ();
124         priv->factory = NULL;
125         priv->toolbar = NULL;
126         //priv->menubar = NULL;
127 }
128
129
130
131 static void
132 save_settings (ModestEditMsgWindow *self)
133 {
134         ModestEditMsgWindowPrivate *priv;
135         ModestConf *conf;
136
137         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(self);
138         conf = modest_tny_platform_factory_get_modest_conf_instance (priv->fact);
139
140         modest_widget_memory_save (conf, G_OBJECT(self),
141                                             "modest-edit-msg-window");
142 }
143
144
145 static void
146 restore_settings (ModestEditMsgWindow *self)
147 {
148         ModestEditMsgWindowPrivate *priv;
149         ModestConf *conf;
150
151         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(self);
152         conf = modest_tny_platform_factory_get_modest_conf_instance (priv->fact);
153
154         modest_widget_memory_restore (conf, G_OBJECT(self),
155                                                "modest-edit-msg-window");
156 }
157
158         
159
160
161 static void
162 send_mail (ModestEditMsgWindow *self)
163 {
164         const gchar *to, *cc, *bcc, *subject;
165         gchar *body, *from;
166         ModestEditMsgWindowPrivate *priv;
167         TnyTransportAccount *transport_account;
168         ModestMailOperation *mail_operation;
169         ModestAccountData *data;
170         
171         GtkTextBuffer *buf;
172         GtkTextIter b, e;
173         
174         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(self);
175         data = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
176
177         /* don't free these (except from) */
178         from    =  g_strdup_printf ("%s <%s>", data->full_name, data->email) ;
179         to      =  gtk_entry_get_text (GTK_ENTRY(priv->to_field));
180         cc      =  gtk_entry_get_text (GTK_ENTRY(priv->cc_field));
181         bcc     =  gtk_entry_get_text (GTK_ENTRY(priv->bcc_field));
182         subject =  gtk_entry_get_text (GTK_ENTRY(priv->subject_field));
183         
184         /* don't unref */
185         buf   =  gtk_text_view_get_buffer (GTK_TEXT_VIEW(priv->msg_body));
186         
187         gtk_text_buffer_get_bounds (buf, &b, &e);
188         body  = gtk_text_buffer_get_text (buf, &b, &e,
189                                           FALSE); /* free this one */
190
191         /* FIXME: Code added just for testing. The transport_account
192            should be provided by the account manager, maybe using
193            _get_current_account () or _get_default_account
194            (TRANSPORT_ACCOUNT). These methods do not exist currently. */
195         {
196                 TnyList *accounts;
197                 TnyIterator *iter;
198                 TnyAccountStore *account_store;
199
200                 accounts = TNY_LIST(tny_simple_list_new ());
201                 account_store = tny_platform_factory_new_account_store (priv->fact);
202                 tny_account_store_get_accounts (account_store, accounts,
203                                                 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
204
205                 iter = tny_list_create_iterator(accounts);
206                 tny_iterator_first (iter);
207                 if (tny_iterator_is_done (iter)) {
208                         /* FIXME: Add error handling through mail operation */
209                         g_printerr("modest: no transport accounts defined\n");
210                         g_free (body);
211                         return;
212                 }
213                 transport_account = TNY_TRANSPORT_ACCOUNT (tny_iterator_get_current(iter));
214         }
215
216         mail_operation = modest_mail_operation_new ();
217
218         modest_mail_operation_send_new_mail (mail_operation,
219                                              transport_account,
220                                              from, to, cc, bcc,
221                                              subject, body, NULL);
222         /* Clean up */
223         g_object_unref (mail_operation);
224         g_free (from);
225         g_free (body);
226 }
227
228
229 static void
230 on_toolbar_button_clicked (ModestToolbar *toolbar, ModestToolbarButton button_id,
231                            ModestEditMsgWindow *self)
232 {
233         switch (button_id) {
234         case MODEST_TOOLBAR_BUTTON_MAIL_SEND:
235                 send_mail (self);
236                 save_settings (self);
237                 gtk_widget_destroy (GTK_WIDGET(self));
238                 break;
239                 
240         case MODEST_TOOLBAR_BUTTON_REPLY:
241         case MODEST_TOOLBAR_BUTTON_REPLY_ALL:
242         case MODEST_TOOLBAR_BUTTON_FORWARD:
243         case MODEST_TOOLBAR_BUTTON_SEND_RECEIVE:
244         case MODEST_TOOLBAR_BUTTON_NEXT:
245         case MODEST_TOOLBAR_BUTTON_PREV:
246         case MODEST_TOOLBAR_BUTTON_DELETE:
247
248         default:
249                 g_printerr ("modest: key %d pressed\n", button_id);
250         }
251 }
252
253
254
255
256 static ModestToolbar*
257 toolbar_new (ModestEditMsgWindow *self)
258 {
259         int i;
260         ModestToolbar *toolbar;
261         GSList *buttons = NULL;
262         ModestEditMsgWindowPrivate *priv;
263
264         ModestToolbarButton button_ids[] = {
265                 MODEST_TOOLBAR_BUTTON_MAIL_SEND
266         };              
267         
268         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(self);
269
270         for (i = 0 ; i != sizeof(button_ids) / sizeof(ModestToolbarButton); ++i)
271                 buttons = g_slist_append (buttons, GINT_TO_POINTER(button_ids[i]));
272         
273         toolbar = modest_toolbar_new (buttons);
274         g_slist_free (buttons);
275
276         g_signal_connect (G_OBJECT(toolbar), "button_clicked",
277                           G_CALLBACK(on_toolbar_button_clicked), self);
278         
279         return toolbar;
280 }
281
282
283 static void
284 init_window (ModestEditMsgWindow *obj)
285 {
286         GtkWidget *to_button, *cc_button, *bcc_button; 
287         GtkWidget *header_table;
288         GtkWidget *main_vbox;
289         
290         ModestEditMsgWindowPrivate *priv;
291         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
292
293         to_button     = gtk_button_new_with_label (_("To..."));
294         cc_button     = gtk_button_new_with_label (_("Cc..."));
295         bcc_button    = gtk_button_new_with_label (_("Bcc..."));
296
297         priv->from_field    = modest_widget_factory_get_combo_box (priv->factory,
298                                                                    MODEST_COMBO_BOX_TYPE_TRANSPORTS);
299         priv->to_field      = gtk_entry_new_with_max_length (40);
300         priv->cc_field      = gtk_entry_new_with_max_length (40);
301         priv->bcc_field     = gtk_entry_new_with_max_length (40);
302         priv->subject_field = gtk_entry_new_with_max_length (40);
303         
304         header_table = gtk_table_new (5,2, FALSE);
305         
306         gtk_table_attach (GTK_TABLE(header_table), gtk_label_new (_("From:")),
307                           0,1,0,1, GTK_SHRINK, 0, 0, 0);
308         gtk_table_attach (GTK_TABLE(header_table), to_button,     0,1,1,2, GTK_SHRINK, 0, 0, 0);
309         gtk_table_attach (GTK_TABLE(header_table), cc_button,     0,1,2,3, GTK_SHRINK, 0, 0, 0);
310         gtk_table_attach (GTK_TABLE(header_table), bcc_button,    0,1,3,4, GTK_SHRINK, 0, 0, 0);
311         gtk_table_attach (GTK_TABLE(header_table), gtk_label_new (_("Subject:")),
312                           0,1,4,5, GTK_SHRINK, 0, 0, 0);
313
314         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->from_field,   1,2,0,1);
315         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->to_field,     1,2,1,2);
316         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->cc_field,     1,2,2,3);
317         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->bcc_field,    1,2,3,4);
318         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->subject_field,1,2,4,5);
319
320         priv->msg_body = gtk_text_view_new ();
321         
322         main_vbox = gtk_vbox_new  (FALSE, 6);
323
324         //priv->menubar = menubar_new (obj);
325         priv->toolbar = GTK_WIDGET(toolbar_new (obj));
326
327         //gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 0);
328         gtk_box_pack_start (GTK_BOX(main_vbox), header_table, FALSE, FALSE, 6);
329         gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 6);
330         gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
331         
332         gtk_widget_show_all (GTK_WIDGET(main_vbox));
333         gtk_container_add (GTK_CONTAINER(obj), main_vbox);
334 }
335         
336
337
338 static void
339 modest_edit_msg_window_finalize (GObject *obj)
340 {
341         ModestEditMsgWindowPrivate *priv;
342
343         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
344
345         g_object_unref (G_OBJECT(priv->factory));
346         priv->factory = NULL;
347         
348         G_OBJECT_CLASS(parent_class)->finalize (obj);
349
350 }
351
352
353
354 static gboolean
355 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestEditMsgWindow *self)
356 {
357         save_settings (self);
358         return FALSE;
359 }
360
361
362 GtkWidget*
363 modest_edit_msg_window_new (ModestWidgetFactory *factory, ModestEditType type)
364 {
365         GObject *obj;
366         ModestEditMsgWindowPrivate *priv;
367
368         g_return_val_if_fail (factory, NULL);
369         g_return_val_if_fail (type < MODEST_EDIT_TYPE_NUM, NULL);
370         
371         obj = g_object_new(MODEST_TYPE_EDIT_MSG_WINDOW, NULL);
372         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
373
374         g_object_ref (factory);
375         priv->factory = factory;
376
377         init_window (MODEST_EDIT_MSG_WINDOW(obj));
378
379         restore_settings (MODEST_EDIT_MSG_WINDOW(obj));
380         
381         gtk_window_set_title (GTK_WINDOW(obj), "Modest");
382         gtk_window_set_icon  (GTK_WINDOW(obj),
383                               modest_icon_factory_get_icon (MODEST_APP_ICON));
384
385         g_signal_connect (G_OBJECT(obj), "delete-event",
386                           G_CALLBACK(on_delete_event), obj);
387         
388
389         return GTK_WIDGET (obj);
390 }
391
392
393
394 void
395 modest_edit_msg_window_set_msg (ModestEditMsgWindow *self, TnyMsg *msg)
396 {
397         TnyHeader *header;
398         GtkTextBuffer *buf;
399         const gchar *to, *cc, *bcc, *subject;
400         ModestEditMsgWindowPrivate *priv;
401
402         g_return_if_fail (MODEST_IS_EDIT_MSG_WINDOW (self));
403         g_return_if_fail (TNY_IS_MSG (msg));
404
405         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE (self);
406
407         header = tny_msg_get_header (msg);
408         to      = tny_header_get_to (header);
409         cc      = tny_header_get_cc (header);
410         bcc     = tny_header_get_bcc (header);
411         subject = tny_header_get_subject (header);
412
413         if (to)
414                 gtk_entry_set_text (GTK_ENTRY(priv->to_field),  to);
415         if (cc)
416                 gtk_entry_set_text (GTK_ENTRY(priv->cc_field),  cc);
417         if (bcc)
418                 gtk_entry_set_text (GTK_ENTRY(priv->bcc_field), bcc);
419         if (subject)
420                 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);   
421         
422         buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(priv->msg_body));
423         gtk_text_buffer_set_text (buf,
424                                   (const gchar *) modest_tny_msg_actions_find_body (msg, TRUE),
425                                   -1);
426
427         /* TODO: lower priority, select in the From: combo to the
428            value that comes from msg <- not sure, should it be
429            allowed? */
430         
431         /* TODO: set attachments */
432 }