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