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-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>
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);
49 typedef struct _ModestEditMsgWindowPrivate ModestEditMsgWindowPrivate;
50 struct _ModestEditMsgWindowPrivate {
52 ModestWidgetFactory *factory;
53 TnyPlatformFactory *fact;
55 GtkWidget *toolbar, *menubar;
57 GtkWidget *from_field, *to_field, *cc_field, *bcc_field,
60 #define MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
61 MODEST_TYPE_EDIT_MSG_WINDOW, \
62 ModestEditMsgWindowPrivate))
64 static GtkWindowClass *parent_class = NULL;
66 /* uncomment the following if you have defined any signals */
67 /* static guint signals[LAST_SIGNAL] = {0}; */
70 modest_edit_msg_window_get_type (void)
72 static GType my_type = 0;
74 static const GTypeInfo my_info = {
75 sizeof(ModestEditMsgWindowClass),
77 NULL, /* base finalize */
78 (GClassInitFunc) modest_edit_msg_window_class_init,
79 NULL, /* class finalize */
80 NULL, /* class data */
81 sizeof(ModestEditMsgWindow),
83 (GInstanceInitFunc) modest_edit_msg_window_init,
86 my_type = g_type_register_static (GTK_TYPE_WINDOW,
87 "ModestEditMsgWindow",
94 modest_edit_msg_window_class_init (ModestEditMsgWindowClass *klass)
96 GObjectClass *gobject_class;
97 gobject_class = (GObjectClass*) klass;
99 parent_class = g_type_class_peek_parent (klass);
100 gobject_class->finalize = modest_edit_msg_window_finalize;
102 g_type_class_add_private (gobject_class, sizeof(ModestEditMsgWindowPrivate));
104 /* signal definitions go here, e.g.: */
105 /* signals[MY_SIGNAL_1] = */
106 /* g_signal_new ("my_signal_1",....); */
107 /* signals[MY_SIGNAL_2] = */
108 /* g_signal_new ("my_signal_2",....); */
113 modest_edit_msg_window_init (ModestEditMsgWindow *obj)
115 ModestEditMsgWindowPrivate *priv;
116 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
118 priv->fact = modest_tny_platform_factory_get_instance ();
119 priv->factory = NULL;
120 priv->toolbar = NULL;
121 priv->menubar = NULL;
127 save_settings (ModestEditMsgWindow *self)
129 ModestEditMsgWindowPrivate *priv;
132 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(self);
133 conf = modest_tny_platform_factory_get_modest_conf_instance (priv->fact);
135 modest_widget_memory_save (conf, G_OBJECT(self), "modest-edit-msg-window");
140 restore_settings (ModestEditMsgWindow *self)
142 ModestEditMsgWindowPrivate *priv;
145 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(self);
146 conf = modest_tny_platform_factory_get_modest_conf_instance (priv->fact);
148 modest_widget_memory_restore (conf, G_OBJECT(self), "modest-edit-msg-window");
154 on_menu_quit (ModestEditMsgWindow *self, guint action, GtkWidget *widget)
156 save_settings (self);
157 gtk_widget_destroy (GTK_WIDGET(self));
164 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
165 static GtkItemFactoryEntry menu_items[] = {
166 { "/_File", NULL, NULL, 0, "<Branch>" ,NULL},
167 { "/File/_New", "<control>N", NULL, 0, "<StockItem>", GTK_STOCK_NEW },
168 { "/File/_Open", "<control>O", NULL, 0, "<StockItem>", GTK_STOCK_OPEN },
169 { "/File/_Save", "<control>S", NULL, 0, "<StockItem>", GTK_STOCK_SAVE },
170 { "/File/Save _As", NULL, NULL, 0, "<Item>", NULL} ,
171 { "/File/Save Draft", "<control><shift>S", NULL, 0, "<Item>",NULL },
174 { "/File/sep1", NULL, NULL, 0, "<Separator>" ,NULL },
175 { "/File/_Quit", "<CTRL>Q", on_menu_quit, 0, "<StockItem>", GTK_STOCK_QUIT },
177 { "/_Edit", NULL, NULL, 0, "<Branch>" ,NULL },
178 { "/Edit/_Undo", "<CTRL>Z", NULL, 0, "<StockItem>", GTK_STOCK_UNDO },
179 { "/Edit/_Redo", "<shift><CTRL>Z", NULL, 0, "<StockItem>", GTK_STOCK_REDO },
180 { "/File/sep1", NULL, NULL, 0, "<Separator>",NULL },
181 { "/Edit/Cut", "<control>X", NULL, 0, "<StockItem>", GTK_STOCK_CUT },
182 { "/Edit/Copy", "<CTRL>C", NULL, 0, "<StockItem>", GTK_STOCK_COPY },
183 { "/Edit/Paste", NULL, NULL, 0, "<StockItem>", GTK_STOCK_PASTE},
184 { "/Edit/sep1", NULL, NULL, 0, "<Separator>",NULL },
185 { "/Edit/Delete", "<CTRL>Q", NULL, 0, "<Item>" ,NULL },
186 { "/Edit/Select all", "<CTRL>A", NULL, 0, "<Item>" ,NULL },
187 { "/Edit/Deselect all", "<Shift><CTRL>A", NULL, 0, "<Item>",NULL },
189 { "/_View", NULL, NULL, 0, "<Branch>",NULL },
190 { "/View/To-field", NULL, NULL, 0, "<CheckItem>",NULL },
192 { "/View/Cc-field:", NULL, NULL, 0, "<CheckItem>",NULL },
193 { "/View/Bcc-field:", NULL, NULL, 0, "<CheckItem>",NULL },
196 { "/_Insert", NULL, NULL, 0, "<Branch>",NULL },
197 /* { "/Actions/_Reply", NULL, NULL, 0, "<Item>" }, */
198 /* { "/Actions/_Forward", NULL, NULL, 0, "<Item>" }, */
199 /* { "/Actions/_Bounce", NULL, NULL, 0, "<Item>" }, */
201 { "/_Format", NULL, NULL, 0, "<Branch>",NULL }
202 /* { "/Options/_Accounts", NULL, on_menu_accounts,0, "<Item>" }, */
203 /* { "/Options/_Contacts", NULL, NULL, 0, "<Item>" }, */
206 /* { "/_Help", NULL, NULL, 0, "<Branch>" }, */
207 /* { "/_Help/About", NULL, on_menu_about, 0, "<StockItem>", GTK_STOCK_ABOUT}, */
210 static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
214 menubar_new (ModestEditMsgWindow *self)
216 GtkItemFactory *item_factory;
217 GtkAccelGroup *accel_group;
219 /* Make an accelerator group (shortcut keys) */
220 accel_group = gtk_accel_group_new ();
222 /* Make an ItemFactory (that makes a menubar) */
223 item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>",
226 /* This function generates the menu items. Pass the item factory,
227 the number of items in the array, the array itself, and any
228 callback data for the the menu items. */
229 gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, self);
231 ///* Attach the new accelerator group to the window. */
232 gtk_window_add_accel_group (GTK_WINDOW (self), accel_group);
234 /* Finally, return the actual menu bar created by the item factory. */
235 return gtk_item_factory_get_widget (item_factory, "<main>");
240 send_mail (ModestEditMsgWindow *self)
242 const gchar *to, *cc, *bcc, *subject;
244 ModestEditMsgWindowPrivate *priv;
245 TnyTransportAccount *transport_account;
246 ModestMailOperation *mail_operation;
247 ModestAccountData *data;
252 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(self);
253 data = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
255 /* don't free these (except from) */
256 from = g_strdup_printf ("%s <%s>", data->full_name, data->email) ;
257 to = gtk_entry_get_text (GTK_ENTRY(priv->to_field));
258 cc = gtk_entry_get_text (GTK_ENTRY(priv->cc_field));
259 bcc = gtk_entry_get_text (GTK_ENTRY(priv->bcc_field));
260 subject = gtk_entry_get_text (GTK_ENTRY(priv->subject_field));
263 buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(priv->msg_body));
265 gtk_text_buffer_get_bounds (buf, &b, &e);
266 body = gtk_text_buffer_get_text (buf, &b, &e,
267 FALSE); /* free this one */
269 /* FIXME: Code added just for testing. The final version will
270 use the send queue provided by tinymail and some
275 TnyAccountStore *account_store;
277 accounts = TNY_LIST(tny_simple_list_new ());
278 account_store = tny_platform_factory_new_account_store (priv->fact);
279 tny_account_store_get_accounts (account_store, accounts,
280 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
282 iter = tny_list_create_iterator(accounts);
283 tny_iterator_first (iter);
284 if (tny_iterator_is_done (iter)) {
285 /* FIXME: Add error handling through mail operation */
286 g_printerr("modest: no transport accounts defined\n");
290 transport_account = TNY_TRANSPORT_ACCOUNT (tny_iterator_get_current(iter));
291 g_object_ref (transport_account);
293 tny_list_foreach (accounts, (GFunc) g_object_unref, NULL);
294 g_object_unref (G_OBJECT (accounts));
295 g_object_unref (G_OBJECT (iter));
298 mail_operation = modest_mail_operation_new ();
300 modest_mail_operation_send_new_mail (mail_operation,
303 subject, body, NULL);
305 g_object_unref (G_OBJECT (mail_operation));
306 g_object_unref (G_OBJECT (transport_account));
313 on_toolbar_button_clicked (ModestToolbar *toolbar, ModestToolbarButton button_id,
314 ModestEditMsgWindow *self)
317 case MODEST_TOOLBAR_BUTTON_MAIL_SEND:
319 save_settings (self);
320 gtk_widget_destroy (GTK_WIDGET(self));
323 case MODEST_TOOLBAR_BUTTON_REPLY:
324 case MODEST_TOOLBAR_BUTTON_REPLY_ALL:
325 case MODEST_TOOLBAR_BUTTON_FORWARD:
326 case MODEST_TOOLBAR_BUTTON_SEND_RECEIVE:
327 case MODEST_TOOLBAR_BUTTON_NEXT:
328 case MODEST_TOOLBAR_BUTTON_PREV:
329 case MODEST_TOOLBAR_BUTTON_DELETE:
332 g_printerr ("modest: key %d pressed\n", button_id);
339 static ModestToolbar*
340 toolbar_new (ModestEditMsgWindow *self)
343 ModestToolbar *toolbar;
344 GSList *buttons = NULL;
345 ModestEditMsgWindowPrivate *priv;
347 ModestToolbarButton button_ids[] = {
348 MODEST_TOOLBAR_BUTTON_MAIL_SEND
351 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(self);
353 for (i = 0 ; i != sizeof(button_ids) / sizeof(ModestToolbarButton); ++i)
354 buttons = g_slist_append (buttons, GINT_TO_POINTER(button_ids[i]));
356 toolbar = modest_widget_factory_get_edit_toolbar (priv->factory, buttons);
357 g_slist_free (buttons);
359 g_signal_connect (G_OBJECT(toolbar), "button_clicked",
360 G_CALLBACK(on_toolbar_button_clicked), self);
367 init_window (ModestEditMsgWindow *obj)
369 GtkWidget *to_button, *cc_button, *bcc_button;
370 GtkWidget *header_table;
371 GtkWidget *main_vbox;
373 ModestEditMsgWindowPrivate *priv;
374 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
376 to_button = gtk_button_new_with_label (_("To..."));
377 cc_button = gtk_button_new_with_label (_("Cc..."));
378 bcc_button = gtk_button_new_with_label (_("Bcc..."));
380 priv->from_field = modest_widget_factory_get_combo_box (priv->factory,
381 MODEST_COMBO_BOX_TYPE_TRANSPORTS);
382 priv->to_field = gtk_entry_new_with_max_length (80);
383 priv->cc_field = gtk_entry_new_with_max_length (80);
384 priv->bcc_field = gtk_entry_new_with_max_length (80);
385 priv->subject_field = gtk_entry_new_with_max_length (80);
387 header_table = gtk_table_new (5,2, FALSE);
389 gtk_table_attach (GTK_TABLE(header_table), gtk_label_new (_("From:")),
390 0,1,0,1, GTK_SHRINK, 0, 0, 0);
391 gtk_table_attach (GTK_TABLE(header_table), to_button, 0,1,1,2, GTK_SHRINK, 0, 0, 0);
392 gtk_table_attach (GTK_TABLE(header_table), cc_button, 0,1,2,3, GTK_SHRINK, 0, 0, 0);
393 gtk_table_attach (GTK_TABLE(header_table), bcc_button, 0,1,3,4, GTK_SHRINK, 0, 0, 0);
394 gtk_table_attach (GTK_TABLE(header_table), gtk_label_new (_("Subject:")),
395 0,1,4,5, GTK_SHRINK, 0, 0, 0);
397 gtk_table_attach_defaults (GTK_TABLE(header_table), priv->from_field, 1,2,0,1);
398 gtk_table_attach_defaults (GTK_TABLE(header_table), priv->to_field, 1,2,1,2);
399 gtk_table_attach_defaults (GTK_TABLE(header_table), priv->cc_field, 1,2,2,3);
400 gtk_table_attach_defaults (GTK_TABLE(header_table), priv->bcc_field, 1,2,3,4);
401 gtk_table_attach_defaults (GTK_TABLE(header_table), priv->subject_field,1,2,4,5);
403 priv->msg_body = gtk_text_view_new ();
405 main_vbox = gtk_vbox_new (FALSE, 6);
407 priv->menubar = menubar_new (obj);
408 priv->toolbar = GTK_WIDGET(toolbar_new (obj));
410 gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 0);
411 gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
412 gtk_box_pack_start (GTK_BOX(main_vbox), header_table, FALSE, FALSE, 6);
413 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 6);
415 gtk_widget_show_all (GTK_WIDGET(main_vbox));
416 gtk_container_add (GTK_CONTAINER(obj), main_vbox);
422 modest_edit_msg_window_finalize (GObject *obj)
424 ModestEditMsgWindowPrivate *priv;
426 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
428 g_object_unref (G_OBJECT(priv->factory));
429 priv->factory = NULL;
431 G_OBJECT_CLASS(parent_class)->finalize (obj);
438 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestEditMsgWindow *self)
440 save_settings (self);
446 modest_edit_msg_window_new (ModestWidgetFactory *factory,
450 ModestEditMsgWindowPrivate *priv;
452 g_return_val_if_fail (factory, NULL);
453 g_return_val_if_fail (type < MODEST_EDIT_TYPE_NUM, NULL);
454 /* g_return_val_if_fail (!(type!=MODEST_EDIT_TYPE_NEW && !msg), NULL); */
456 obj = g_object_new(MODEST_TYPE_EDIT_MSG_WINDOW, NULL);
457 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
459 g_object_ref (factory);
460 priv->factory = factory;
462 init_window (MODEST_EDIT_MSG_WINDOW(obj));
464 restore_settings (MODEST_EDIT_MSG_WINDOW(obj));
466 gtk_window_set_title (GTK_WINDOW(obj), "Modest");
467 gtk_window_set_icon (GTK_WINDOW(obj),
468 modest_icon_factory_get_icon (MODEST_APP_ICON));
470 g_signal_connect (G_OBJECT(obj), "delete-event",
471 G_CALLBACK(on_delete_event), obj);
473 return GTK_WIDGET (obj);
477 modest_edit_msg_window_set_msg (ModestEditMsgWindow *self, TnyMsg *msg)
481 const gchar *to, *cc, *bcc, *subject;
482 ModestEditMsgWindowPrivate *priv;
484 g_return_if_fail (MODEST_IS_EDIT_MSG_WINDOW (self));
485 g_return_if_fail (TNY_IS_MSG (msg));
487 priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE (self);
489 header = tny_msg_get_header (msg);
490 to = tny_header_get_to (header);
491 cc = tny_header_get_cc (header);
492 bcc = tny_header_get_bcc (header);
493 subject = tny_header_get_subject (header);
496 gtk_entry_set_text (GTK_ENTRY(priv->to_field), to);
498 gtk_entry_set_text (GTK_ENTRY(priv->cc_field), cc);
500 gtk_entry_set_text (GTK_ENTRY(priv->bcc_field), bcc);
502 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
504 buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW(priv->msg_body));
505 gtk_text_buffer_set_text (buf,
506 (const gchar *) modest_tny_msg_actions_find_body (msg, TRUE),
509 /* TODO: lower priority, select in the From: combo to the
510 value that comes from msg <- not sure, should it be
513 /* TODO: set attachments */