1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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.
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.
29 #include <glib/gi18n.h>
30 #include <tny-account-store.h>
31 #include "modest-toolbar.h"
32 #include "modest-edit-msg-window.h"
33 #include "modest-widget-memory.h"
34 #include "modest-mail-operation.h"
35 #include "modest-tny-platform-factory.h"
36 #include "modest-tny-msg-actions.h"
37 #include <tny-simple-list.h>
39 static void modest_edit_msg_window_class_init (ModestEditMsgWindowClass *klass);
40 static void modest_edit_msg_window_init (ModestEditMsgWindow *obj);
41 static void modest_edit_msg_window_finalize (GObject *obj);
50 typedef struct _ModestEditMsgWindowPrivate ModestEditMsgWindowPrivate;
51 struct _ModestEditMsgWindowPrivate {
53 ModestWidgetFactory *factory;
54 TnyPlatformFactory *fact;
56 GtkWidget *toolbar, *menubar;
58 GtkWidget *from_field, *to_field, *cc_field, *bcc_field,
61 #define MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
62 MODEST_TYPE_EDIT_MSG_WINDOW, \
63 ModestEditMsgWindowPrivate))
65 static GtkWindowClass *parent_class = NULL;
67 /* uncomment the following if you have defined any signals */
68 /* static guint signals[LAST_SIGNAL] = {0}; */
71 modest_edit_msg_window_get_type (void)
73 static GType my_type = 0;
75 static const GTypeInfo my_info = {
76 sizeof(ModestEditMsgWindowClass),
78 NULL, /* base finalize */
79 (GClassInitFunc) modest_edit_msg_window_class_init,
80 NULL, /* class finalize */
81 NULL, /* class data */
82 sizeof(ModestEditMsgWindow),
84 (GInstanceInitFunc) modest_edit_msg_window_init,
87 my_type = g_type_register_static (GTK_TYPE_WINDOW,
88 "ModestEditMsgWindow",
95 modest_edit_msg_window_class_init (ModestEditMsgWindowClass *klass)
97 GObjectClass *gobject_class;
98 gobject_class = (GObjectClass*) klass;
100 parent_class = g_type_class_peek_parent (klass);
101 gobject_class->finalize = modest_edit_msg_window_finalize;
103 g_type_class_add_private (gobject_class, sizeof(ModestEditMsgWindowPrivate));
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",....); */
114 modest_edit_msg_window_init (ModestEditMsgWindow *obj)
116 ModestEditMsgWindowPrivate *priv;
117 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
119 priv->fact = modest_tny_platform_factory_get_instance ();
120 priv->factory = NULL;
121 priv->toolbar = NULL;
122 priv->menubar = NULL;
128 save_settings (ModestEditMsgWindow *self)
130 ModestEditMsgWindowPrivate *priv;
133 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(self);
134 conf = modest_tny_platform_factory_get_modest_conf_instance (priv->fact);
136 modest_widget_memory_save (conf, G_OBJECT(self), "modest-edit-msg-window");
141 restore_settings (ModestEditMsgWindow *self)
143 ModestEditMsgWindowPrivate *priv;
146 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(self);
147 conf = modest_tny_platform_factory_get_modest_conf_instance (priv->fact);
149 modest_widget_memory_restore (conf, G_OBJECT(self), "modest-edit-msg-window");
155 on_menu_quit (ModestEditMsgWindow *self, guint action, GtkWidget *widget)
157 save_settings (self);
158 gtk_widget_destroy (GTK_WIDGET(self));
165 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
166 static GtkItemFactoryEntry menu_items[] = {
167 { "/_File", NULL, NULL, 0, "<Branch>" ,NULL},
168 { "/File/_New", "<control>N", NULL, 0, "<StockItem>", GTK_STOCK_NEW },
169 { "/File/_Open", "<control>O", NULL, 0, "<StockItem>", GTK_STOCK_OPEN },
170 { "/File/_Save", "<control>S", NULL, 0, "<StockItem>", GTK_STOCK_SAVE },
171 { "/File/Save _As", NULL, NULL, 0, "<Item>", NULL} ,
172 { "/File/Save Draft", "<control><shift>S", NULL, 0, "<Item>",NULL },
175 { "/File/sep1", NULL, NULL, 0, "<Separator>" ,NULL },
176 { "/File/_Quit", "<CTRL>Q", on_menu_quit, 0, "<StockItem>", GTK_STOCK_QUIT },
178 { "/_Edit", NULL, NULL, 0, "<Branch>" ,NULL },
179 { "/Edit/_Undo", "<CTRL>Z", NULL, 0, "<StockItem>", GTK_STOCK_UNDO },
180 { "/Edit/_Redo", "<shift><CTRL>Z", NULL, 0, "<StockItem>", GTK_STOCK_REDO },
181 { "/File/sep1", NULL, NULL, 0, "<Separator>",NULL },
182 { "/Edit/Cut", "<control>X", NULL, 0, "<StockItem>", GTK_STOCK_CUT },
183 { "/Edit/Copy", "<CTRL>C", NULL, 0, "<StockItem>", GTK_STOCK_COPY },
184 { "/Edit/Paste", NULL, NULL, 0, "<StockItem>", GTK_STOCK_PASTE},
185 { "/Edit/sep1", NULL, NULL, 0, "<Separator>",NULL },
186 { "/Edit/Delete", "<CTRL>Q", NULL, 0, "<Item>" ,NULL },
187 { "/Edit/Select all", "<CTRL>A", NULL, 0, "<Item>" ,NULL },
188 { "/Edit/Deselect all", "<Shift><CTRL>A", NULL, 0, "<Item>",NULL },
190 { "/_View", NULL, NULL, 0, "<Branch>",NULL },
191 { "/View/To-field", NULL, NULL, 0, "<CheckItem>",NULL },
193 { "/View/Cc-field:", NULL, NULL, 0, "<CheckItem>",NULL },
194 { "/View/Bcc-field:", NULL, NULL, 0, "<CheckItem>",NULL },
197 { "/_Insert", NULL, NULL, 0, "<Branch>",NULL },
198 /* { "/Actions/_Reply", NULL, NULL, 0, "<Item>" }, */
199 /* { "/Actions/_Forward", NULL, NULL, 0, "<Item>" }, */
200 /* { "/Actions/_Bounce", NULL, NULL, 0, "<Item>" }, */
202 { "/_Format", NULL, NULL, 0, "<Branch>",NULL }
203 /* { "/Options/_Accounts", NULL, on_menu_accounts,0, "<Item>" }, */
204 /* { "/Options/_Contacts", NULL, NULL, 0, "<Item>" }, */
207 /* { "/_Help", NULL, NULL, 0, "<Branch>" }, */
208 /* { "/_Help/About", NULL, on_menu_about, 0, "<StockItem>", GTK_STOCK_ABOUT}, */
211 static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
215 menubar_new (ModestEditMsgWindow *self)
217 GtkItemFactory *item_factory;
218 GtkAccelGroup *accel_group;
220 /* Make an accelerator group (shortcut keys) */
221 accel_group = gtk_accel_group_new ();
223 /* Make an ItemFactory (that makes a menubar) */
224 item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>",
227 /* This function generates the menu items. Pass the item factory,
228 the number of items in the array, the array itself, and any
229 callback data for the the menu items. */
230 gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, self);
232 ///* Attach the new accelerator group to the window. */
233 gtk_window_add_accel_group (GTK_WINDOW (self), accel_group);
235 /* Finally, return the actual menu bar created by the item factory. */
236 return gtk_item_factory_get_widget (item_factory, "<main>");
241 send_mail (ModestEditMsgWindow *self)
243 const gchar *to, *cc, *bcc, *subject;
245 ModestEditMsgWindowPrivate *priv;
246 TnyTransportAccount *transport_account;
247 ModestMailOperation *mail_operation;
248 ModestAccountData *data;
253 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(self);
254 data = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
256 /* don't free these (except from) */
257 from = g_strdup_printf ("%s <%s>", data->full_name, data->email) ;
258 to = gtk_entry_get_text (GTK_ENTRY(priv->to_field));
259 cc = gtk_entry_get_text (GTK_ENTRY(priv->cc_field));
260 bcc = gtk_entry_get_text (GTK_ENTRY(priv->bcc_field));
261 subject = gtk_entry_get_text (GTK_ENTRY(priv->subject_field));
264 buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(priv->msg_body));
266 gtk_text_buffer_get_bounds (buf, &b, &e);
267 body = gtk_text_buffer_get_text (buf, &b, &e,
268 FALSE); /* free this one */
270 /* FIXME: Code added just for testing. The final version will
271 use the send queue provided by tinymail and some
276 TnyAccountStore *account_store;
278 accounts = TNY_LIST(tny_simple_list_new ());
279 account_store = tny_platform_factory_new_account_store (priv->fact);
280 tny_account_store_get_accounts (account_store, accounts,
281 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
283 iter = tny_list_create_iterator(accounts);
284 tny_iterator_first (iter);
285 if (tny_iterator_is_done (iter)) {
286 /* FIXME: Add error handling through mail operation */
287 g_printerr("modest: no transport accounts defined\n");
291 transport_account = TNY_TRANSPORT_ACCOUNT (tny_iterator_get_current(iter));
292 g_object_ref (transport_account);
294 tny_list_foreach (accounts, (GFunc) g_object_unref, NULL);
295 g_object_unref (G_OBJECT (accounts));
296 g_object_unref (G_OBJECT (iter));
299 mail_operation = modest_mail_operation_new ();
301 modest_mail_operation_send_new_mail (mail_operation,
304 subject, body, NULL);
306 g_object_unref (G_OBJECT (mail_operation));
307 g_object_unref (G_OBJECT (transport_account));
314 on_toolbar_button_clicked (ModestToolbar *toolbar, ModestToolbarButton button_id,
315 ModestEditMsgWindow *self)
318 case MODEST_TOOLBAR_BUTTON_MAIL_SEND:
320 save_settings (self);
321 gtk_widget_destroy (GTK_WIDGET(self));
324 case MODEST_TOOLBAR_BUTTON_REPLY:
325 case MODEST_TOOLBAR_BUTTON_REPLY_ALL:
326 case MODEST_TOOLBAR_BUTTON_FORWARD:
327 case MODEST_TOOLBAR_BUTTON_SEND_RECEIVE:
328 case MODEST_TOOLBAR_BUTTON_NEXT:
329 case MODEST_TOOLBAR_BUTTON_PREV:
330 case MODEST_TOOLBAR_BUTTON_DELETE:
333 g_printerr ("modest: key %d pressed\n", button_id);
340 static ModestToolbar*
341 toolbar_new (ModestEditMsgWindow *self)
344 ModestToolbar *toolbar;
345 GSList *buttons = NULL;
346 ModestEditMsgWindowPrivate *priv;
348 ModestToolbarButton button_ids[] = {
349 MODEST_TOOLBAR_BUTTON_MAIL_SEND
352 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(self);
354 for (i = 0 ; i != sizeof(button_ids) / sizeof(ModestToolbarButton); ++i)
355 buttons = g_slist_append (buttons, GINT_TO_POINTER(button_ids[i]));
357 toolbar = modest_toolbar_new (buttons);
358 g_slist_free (buttons);
360 g_signal_connect (G_OBJECT(toolbar), "button_clicked",
361 G_CALLBACK(on_toolbar_button_clicked), self);
368 init_window (ModestEditMsgWindow *obj)
370 GtkWidget *to_button, *cc_button, *bcc_button;
371 GtkWidget *header_table;
372 GtkWidget *main_vbox;
374 ModestEditMsgWindowPrivate *priv;
375 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
377 to_button = gtk_button_new_with_label (_("To..."));
378 cc_button = gtk_button_new_with_label (_("Cc..."));
379 bcc_button = gtk_button_new_with_label (_("Bcc..."));
381 priv->from_field = modest_widget_factory_get_combo_box (priv->factory,
382 MODEST_COMBO_BOX_TYPE_TRANSPORTS);
383 priv->to_field = gtk_entry_new_with_max_length (80);
384 priv->cc_field = gtk_entry_new_with_max_length (80);
385 priv->bcc_field = gtk_entry_new_with_max_length (80);
386 priv->subject_field = gtk_entry_new_with_max_length (80);
388 header_table = gtk_table_new (5,2, FALSE);
390 gtk_table_attach (GTK_TABLE(header_table), gtk_label_new (_("From:")),
391 0,1,0,1, GTK_SHRINK, 0, 0, 0);
392 gtk_table_attach (GTK_TABLE(header_table), to_button, 0,1,1,2, GTK_SHRINK, 0, 0, 0);
393 gtk_table_attach (GTK_TABLE(header_table), cc_button, 0,1,2,3, GTK_SHRINK, 0, 0, 0);
394 gtk_table_attach (GTK_TABLE(header_table), bcc_button, 0,1,3,4, GTK_SHRINK, 0, 0, 0);
395 gtk_table_attach (GTK_TABLE(header_table), gtk_label_new (_("Subject:")),
396 0,1,4,5, GTK_SHRINK, 0, 0, 0);
398 gtk_table_attach_defaults (GTK_TABLE(header_table), priv->from_field, 1,2,0,1);
399 gtk_table_attach_defaults (GTK_TABLE(header_table), priv->to_field, 1,2,1,2);
400 gtk_table_attach_defaults (GTK_TABLE(header_table), priv->cc_field, 1,2,2,3);
401 gtk_table_attach_defaults (GTK_TABLE(header_table), priv->bcc_field, 1,2,3,4);
402 gtk_table_attach_defaults (GTK_TABLE(header_table), priv->subject_field,1,2,4,5);
404 priv->msg_body = gtk_text_view_new ();
406 main_vbox = gtk_vbox_new (FALSE, 6);
408 priv->menubar = menubar_new (obj);
409 priv->toolbar = GTK_WIDGET(toolbar_new (obj));
411 gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 0);
412 gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
413 gtk_box_pack_start (GTK_BOX(main_vbox), header_table, FALSE, FALSE, 6);
414 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 6);
416 gtk_widget_show_all (GTK_WIDGET(main_vbox));
417 gtk_container_add (GTK_CONTAINER(obj), main_vbox);
423 modest_edit_msg_window_finalize (GObject *obj)
425 ModestEditMsgWindowPrivate *priv;
427 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
429 g_object_unref (G_OBJECT(priv->factory));
430 priv->factory = NULL;
432 G_OBJECT_CLASS(parent_class)->finalize (obj);
439 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestEditMsgWindow *self)
441 save_settings (self);
447 modest_edit_msg_window_new (ModestWidgetFactory *factory,
451 ModestEditMsgWindowPrivate *priv;
453 g_return_val_if_fail (factory, NULL);
454 g_return_val_if_fail (type < MODEST_EDIT_TYPE_NUM, NULL);
455 /* g_return_val_if_fail (!(type!=MODEST_EDIT_TYPE_NEW && !msg), NULL); */
457 obj = g_object_new(MODEST_TYPE_EDIT_MSG_WINDOW, NULL);
458 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
460 g_object_ref (factory);
461 priv->factory = factory;
463 init_window (MODEST_EDIT_MSG_WINDOW(obj));
465 restore_settings (MODEST_EDIT_MSG_WINDOW(obj));
467 gtk_window_set_title (GTK_WINDOW(obj), "Modest");
468 gtk_window_set_icon (GTK_WINDOW(obj),
469 modest_icon_factory_get_icon (MODEST_APP_ICON));
471 g_signal_connect (G_OBJECT(obj), "delete-event",
472 G_CALLBACK(on_delete_event), obj);
474 return GTK_WIDGET (obj);
478 modest_edit_msg_window_set_msg (ModestEditMsgWindow *self, TnyMsg *msg)
482 const gchar *to, *cc, *bcc, *subject;
483 ModestEditMsgWindowPrivate *priv;
485 g_return_if_fail (MODEST_IS_EDIT_MSG_WINDOW (self));
486 g_return_if_fail (TNY_IS_MSG (msg));
488 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE (self);
490 header = tny_msg_get_header (msg);
491 to = tny_header_get_to (header);
492 cc = tny_header_get_cc (header);
493 bcc = tny_header_get_bcc (header);
494 subject = tny_header_get_subject (header);
497 gtk_entry_set_text (GTK_ENTRY(priv->to_field), to);
499 gtk_entry_set_text (GTK_ENTRY(priv->cc_field), cc);
501 gtk_entry_set_text (GTK_ENTRY(priv->bcc_field), bcc);
503 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
505 buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(priv->msg_body));
506 gtk_text_buffer_set_text (buf,
507 (const gchar *) modest_tny_msg_actions_find_body (msg, TRUE),
510 /* TODO: lower priority, select in the From: combo to the
511 value that comes from msg <- not sure, should it be
514 /* TODO: set attachments */