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.
30 #include <glib/gi18n.h>
32 #include <camel/camel-url.h>
33 #include <widgets/modest-combo-box.h>
34 #include "modest-account-assistant.h"
35 #include "modest-store-widget.h"
36 #include "modest-transport-widget.h"
37 #include "modest-text-utils.h"
38 #include <modest-protocol-info.h>
42 /* 'private'/'protected' functions */
43 static void modest_account_assistant_class_init (ModestAccountAssistantClass *klass);
44 static void modest_account_assistant_init (ModestAccountAssistant *obj);
45 static void modest_account_assistant_finalize (GObject *obj);
54 typedef struct _ModestAccountAssistantPrivate ModestAccountAssistantPrivate;
55 struct _ModestAccountAssistantPrivate {
57 ModestAccountMgr *account_mgr;
59 GtkWidget *account_name;
63 GtkWidget *store_widget;
64 GtkWidget *transport_widget;
66 GtkWidget *transport_holder;
67 GtkWidget *store_holder;
69 ModestPairList *receiving_transport_store_protos;
70 ModestPairList *sending_transport_store_protos;
73 #define MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
74 MODEST_TYPE_ACCOUNT_ASSISTANT, \
75 ModestAccountAssistantPrivate))
77 static GtkAssistantClass *parent_class = NULL;
79 /* uncomment the following if you have defined any signals */
80 /* static guint signals[LAST_SIGNAL] = {0}; */
83 modest_account_assistant_get_type (void)
85 static GType my_type = 0;
87 static const GTypeInfo my_info = {
88 sizeof(ModestAccountAssistantClass),
90 NULL, /* base finalize */
91 (GClassInitFunc) modest_account_assistant_class_init,
92 NULL, /* class finalize */
93 NULL, /* class data */
94 sizeof(ModestAccountAssistant),
96 (GInstanceInitFunc) modest_account_assistant_init,
99 my_type = g_type_register_static (GTK_TYPE_ASSISTANT,
100 "ModestAccountAssistant",
107 modest_account_assistant_class_init (ModestAccountAssistantClass *klass)
109 GObjectClass *gobject_class;
110 gobject_class = (GObjectClass*) klass;
112 parent_class = g_type_class_peek_parent (klass);
113 gobject_class->finalize = modest_account_assistant_finalize;
115 g_type_class_add_private (gobject_class, sizeof(ModestAccountAssistantPrivate));
117 /* signal definitions go here, e.g.: */
118 /* signals[MY_SIGNAL_1] = */
119 /* g_signal_new ("my_signal_1",....); */
120 /* signals[MY_SIGNAL_2] = */
121 /* g_signal_new ("my_signal_2",....); */
128 add_intro_page (ModestAccountAssistant *assistant)
130 GtkWidget *page, *label;
132 page = gtk_vbox_new (FALSE, 6);
134 label = gtk_label_new (
135 _("Welcome to the account assistant\n\n"
136 "It will help to set up a new e-mail account\n"));
137 gtk_box_pack_start (GTK_BOX(page), label, FALSE, FALSE, 6);
138 gtk_widget_show_all (page);
140 gtk_assistant_append_page (GTK_ASSISTANT(assistant), page);
142 gtk_assistant_set_page_title (GTK_ASSISTANT(assistant), page,
143 _("Modest Account Assistant"));
144 gtk_assistant_set_page_type (GTK_ASSISTANT(assistant), page,
145 GTK_ASSISTANT_PAGE_INTRO);
146 gtk_assistant_set_page_complete (GTK_ASSISTANT(assistant),
152 set_current_page_complete (ModestAccountAssistant *self, gboolean complete)
157 pageno = gtk_assistant_get_current_page (GTK_ASSISTANT(self));
160 page = gtk_assistant_get_nth_page (GTK_ASSISTANT(self), pageno);
161 gtk_assistant_set_page_complete (GTK_ASSISTANT(self), page, complete);
167 identity_page_update_completeness (GtkEditable *editable,
168 ModestAccountAssistant *self)
170 ModestAccountAssistantPrivate *priv;
173 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
175 txt = gtk_entry_get_text (GTK_ENTRY(priv->fullname));
176 if (!txt || strlen(txt) == 0) {
177 set_current_page_complete (self, FALSE);
181 /* FIXME: regexp check for email address */
182 txt = gtk_entry_get_text (GTK_ENTRY(priv->email));
183 if (!modest_text_utils_validate_email_address (txt))
184 set_current_page_complete (self, FALSE);
186 set_current_page_complete (self, TRUE);
191 add_identity_page (ModestAccountAssistant *self)
193 GtkWidget *page, *label, *table;
194 ModestAccountAssistantPrivate *priv;
196 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
198 priv->fullname = gtk_entry_new_with_max_length (40);
199 priv->email = gtk_entry_new_with_max_length (40);
201 page = gtk_vbox_new (FALSE, 6);
203 label = gtk_label_new (
204 _("Please enter your name and your e-mail address below.\n\n"));
205 gtk_box_pack_start (GTK_BOX(page), label, FALSE, FALSE, 6);
207 table = gtk_table_new (2,2, FALSE);
208 gtk_table_attach_defaults (GTK_TABLE(table),gtk_label_new (_("Full name")),
210 gtk_table_attach_defaults (GTK_TABLE(table),gtk_label_new (_("E-mail address")),
212 gtk_table_attach_defaults (GTK_TABLE(table),priv->fullname,
214 gtk_table_attach_defaults (GTK_TABLE(table),priv->email,
217 g_signal_connect (G_OBJECT(priv->fullname), "changed",
218 G_CALLBACK(identity_page_update_completeness),
220 g_signal_connect (G_OBJECT(priv->email), "changed",
221 G_CALLBACK(identity_page_update_completeness),
224 gtk_box_pack_start (GTK_BOX(page), table, FALSE, FALSE, 6);
225 gtk_widget_show_all (page);
227 gtk_assistant_append_page (GTK_ASSISTANT(self), page);
229 gtk_assistant_set_page_title (GTK_ASSISTANT(self), page,
231 gtk_assistant_set_page_type (GTK_ASSISTANT(self), page,
232 GTK_ASSISTANT_PAGE_INTRO);
233 gtk_assistant_set_page_complete (GTK_ASSISTANT(self),
239 receiving_page_update_completeness (GtkEditable *editable,
240 ModestAccountAssistant *self)
242 ModestAccountAssistantPrivate *priv;
245 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
247 txt = modest_store_widget_get_username (MODEST_STORE_WIDGET (priv->store_widget));
248 if (!txt || strlen(txt) == 0) {
249 set_current_page_complete (self, FALSE);
253 txt = modest_store_widget_get_servername (MODEST_STORE_WIDGET (priv->store_widget));
254 if (!txt || strlen(txt) == 0) {
255 set_current_page_complete (self, FALSE);
258 set_current_page_complete (self, TRUE);
262 on_receiving_combo_box_changed (GtkComboBox *combo, ModestAccountAssistant *self)
264 ModestAccountAssistantPrivate *priv;
266 ModestTransportStoreProtocol proto;
268 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
269 chosen = gtk_combo_box_get_active_text (GTK_COMBO_BOX(combo));
270 if (priv->store_widget)
271 gtk_container_remove (GTK_CONTAINER(priv->store_holder),
274 proto = modest_protocol_info_get_transport_store_protocol (chosen);
276 /* FIXME: we could have these widgets cached instead of
277 creating them every time */
278 priv->store_widget = modest_store_widget_new (proto);
279 if (proto == MODEST_PROTOCOL_STORE_POP || proto == MODEST_PROTOCOL_STORE_IMAP) {
280 g_signal_connect (priv->store_widget,
282 G_CALLBACK (receiving_page_update_completeness),
284 set_current_page_complete (self, FALSE);
286 set_current_page_complete (self, TRUE);
288 gtk_container_add (GTK_CONTAINER(priv->store_holder),
291 gtk_widget_show_all (priv->store_holder);
296 add_receiving_page (ModestAccountAssistant *self)
298 GtkWidget *page, *box, *combo;
299 ModestAccountAssistantPrivate *priv;
301 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
302 page = gtk_vbox_new (FALSE, 6);
304 gtk_box_pack_start (GTK_BOX(page),
306 _("Please select among the following options")),
308 box = gtk_hbox_new (FALSE, 6);
309 gtk_box_pack_start (GTK_BOX(box),
310 gtk_label_new(_("Server type")),
313 /* Note: This ModestPairList* must exist for as long as the combo
314 * that uses it, because the ModestComboBox uses the ID opaquely,
315 * so it can't know how to manage its memory. */
316 priv->receiving_transport_store_protos = modest_protocol_info_get_transport_store_protocol_pair_list (MODEST_PROTOCOL_TYPE_STORE);
317 combo = modest_combo_box_new (priv->receiving_transport_store_protos, g_str_equal);
319 g_signal_connect (G_OBJECT(combo), "changed",
320 G_CALLBACK(on_receiving_combo_box_changed), self);
322 gtk_box_pack_start (GTK_BOX(box), combo, FALSE,FALSE,6);
323 gtk_box_pack_start (GTK_BOX(page), box, FALSE,FALSE, 6);
325 gtk_box_pack_start (GTK_BOX(page), gtk_hseparator_new(), FALSE, FALSE, 0);
327 priv->store_holder = gtk_hbox_new (FALSE, 0);
328 gtk_box_pack_start (GTK_BOX(page), priv->store_holder,
331 /* Force the selection */
332 on_receiving_combo_box_changed (GTK_COMBO_BOX (combo), self);
334 gtk_assistant_append_page (GTK_ASSISTANT(self), page);
336 gtk_assistant_set_page_title (GTK_ASSISTANT(self), page,
337 _("Receiving mail"));
338 gtk_assistant_set_page_type (GTK_ASSISTANT(self), page,
339 GTK_ASSISTANT_PAGE_INTRO);
340 gtk_assistant_set_page_complete (GTK_ASSISTANT(self),
342 gtk_widget_show_all (page);
349 on_sending_combo_box_changed (GtkComboBox *combo, ModestAccountAssistant *self)
351 ModestAccountAssistantPrivate *priv;
354 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
356 chosen = gtk_combo_box_get_active_text (GTK_COMBO_BOX(combo));
358 if (priv->transport_widget)
359 gtk_container_remove (GTK_CONTAINER(priv->transport_holder),
360 priv->transport_widget);
361 priv->transport_widget =
362 modest_transport_widget_new (modest_protocol_info_get_transport_store_protocol(chosen));
364 gtk_container_add (GTK_CONTAINER(priv->transport_holder),
365 priv->transport_widget);
367 gtk_widget_show_all (priv->transport_holder);
373 add_sending_page (ModestAccountAssistant *self)
375 GtkWidget *page, *box, *combo;
376 ModestAccountAssistantPrivate *priv;
378 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
379 page = gtk_vbox_new (FALSE, 6);
381 gtk_box_pack_start (GTK_BOX(page),
383 _("Please select among the following options")),
385 box = gtk_hbox_new (FALSE, 0);
386 gtk_box_pack_start (GTK_BOX(box),
387 gtk_label_new(_("Server type")),
390 /* Note: This ModestPairList* must exist for as long as the combo
391 * that uses it, because the ModestComboBox uses the ID opaquely,
392 * so it can't know how to manage its memory. */
393 priv->sending_transport_store_protos = modest_protocol_info_get_transport_store_protocol_pair_list (MODEST_PROTOCOL_TYPE_TRANSPORT);
394 combo = modest_combo_box_new (priv->sending_transport_store_protos, g_str_equal);
396 g_signal_connect (G_OBJECT(combo), "changed",
397 G_CALLBACK(on_sending_combo_box_changed), self);
399 gtk_box_pack_start (GTK_BOX(box), combo, FALSE,FALSE,0);
400 gtk_box_pack_start (GTK_BOX(page), box, FALSE,FALSE, 0);
402 gtk_box_pack_start (GTK_BOX(page), gtk_hseparator_new(), FALSE, FALSE, 0);
404 priv->transport_holder = gtk_hbox_new (FALSE, 0);
405 gtk_box_pack_start (GTK_BOX(page), priv->transport_holder,
408 /* Force the selection */
409 on_sending_combo_box_changed (GTK_COMBO_BOX (combo), self);
411 gtk_assistant_append_page (GTK_ASSISTANT(self), page);
413 gtk_assistant_set_page_title (GTK_ASSISTANT(self), page,
415 gtk_assistant_set_page_type (GTK_ASSISTANT(self), page,
416 GTK_ASSISTANT_PAGE_INTRO);
417 gtk_assistant_set_page_complete (GTK_ASSISTANT(self),
419 gtk_widget_show_all (page);
425 add_final_page (ModestAccountAssistant *self)
427 GtkWidget *page, *box;
428 ModestAccountAssistantPrivate *priv;
430 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
431 page = gtk_vbox_new (FALSE, 6);
433 gtk_box_pack_start (GTK_BOX(page),
435 _("We're almost done. Press 'Apply' to store this new account")),
437 box = gtk_hbox_new (FALSE, 6);
439 gtk_entry_new_with_max_length (40);
440 gtk_entry_set_text (GTK_ENTRY(priv->account_name),
441 gtk_entry_get_text(GTK_ENTRY(priv->email)));
442 gtk_box_pack_start (GTK_BOX(box),gtk_label_new(_("Account name:")),
444 gtk_box_pack_start (GTK_BOX(box),priv->account_name , FALSE,FALSE,6);
446 gtk_box_pack_start (GTK_BOX(page), box, FALSE, FALSE, 6);
448 gtk_assistant_append_page (GTK_ASSISTANT(self), page);
450 gtk_assistant_set_page_title (GTK_ASSISTANT(self), page,
451 _("Account Management"));
452 gtk_assistant_set_page_type (GTK_ASSISTANT(self), page,
453 GTK_ASSISTANT_PAGE_CONFIRM);
455 gtk_assistant_set_page_complete (GTK_ASSISTANT(self),
457 gtk_widget_show_all (page);
462 modest_account_assistant_init (ModestAccountAssistant *obj)
464 ModestAccountAssistantPrivate *priv;
465 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(obj);
467 priv->account_mgr = NULL;
469 priv->store_widget = NULL;
470 priv->transport_widget = NULL;
474 modest_account_assistant_finalize (GObject *obj)
476 ModestAccountAssistantPrivate *priv;
478 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(obj);
480 if (priv->account_mgr) {
481 g_object_unref (G_OBJECT(priv->account_mgr));
482 priv->account_mgr = NULL;
485 /* These had to stay alive for as long as the comboboxes that used them: */
486 modest_pair_list_free (priv->receiving_transport_store_protos);
487 modest_pair_list_free (priv->sending_transport_store_protos);
489 G_OBJECT_CLASS(parent_class)->finalize (obj);
493 on_cancel (ModestAccountAssistant *self, gpointer user_data)
499 label = gtk_label_new (_("Are you sure you want to cancel\n"
500 "setting up a new account?"));
502 dialog = gtk_dialog_new_with_buttons (_("Cancel"),
504 GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
505 GTK_STOCK_YES, GTK_RESPONSE_ACCEPT,
506 GTK_STOCK_NO, GTK_RESPONSE_CANCEL,
509 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
510 label, FALSE, FALSE, 6);
512 gtk_widget_show_all ((GTK_DIALOG(dialog)->vbox));
514 gtk_window_set_resizable (GTK_WINDOW(dialog), FALSE);
516 response = gtk_dialog_run (GTK_DIALOG(dialog));
517 gtk_widget_destroy (dialog);
520 case GTK_RESPONSE_ACCEPT:
521 /* close the assistant */
522 gtk_widget_hide (GTK_WIDGET(self));
524 case GTK_RESPONSE_CANCEL:
525 /* don't do anything */
527 default: g_assert_not_reached ();
533 get_account_name (ModestAccountAssistant *self)
535 ModestAccountAssistantPrivate *priv;
536 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
538 return gtk_entry_get_text (GTK_ENTRY(priv->account_name));
542 get_fullname (ModestAccountAssistant *self)
544 ModestAccountAssistantPrivate *priv;
545 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
547 return gtk_entry_get_text (GTK_ENTRY(priv->fullname));
553 get_email (ModestAccountAssistant *self)
555 ModestAccountAssistantPrivate *priv;
556 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
558 return gtk_entry_get_text (GTK_ENTRY(priv->email));
563 on_close (ModestAccountAssistant *self, gpointer user_data)
565 gtk_widget_hide (GTK_WIDGET (self));
570 * FIXME: hmmmm this a Camel internal thing, should move this
574 get_account_uri (ModestTransportStoreProtocol proto, const gchar* path)
580 case MODEST_PROTOCOL_STORE_MBOX:
581 url = camel_url_new ("mbox:", NULL); break;
582 case MODEST_PROTOCOL_STORE_MAILDIR:
583 url = camel_url_new ("maildir:", NULL); break;
585 g_return_val_if_reached (NULL);
587 camel_url_set_path (url, path);
588 uri = camel_url_to_string (url, 0);
589 camel_url_free (url);
595 get_new_server_account_name (ModestAccountMgr* acc_mgr, ModestTransportStoreProtocol proto,
596 const gchar* username, const gchar *servername)
602 name = g_strdup_printf ("%s:%d",
603 modest_protocol_info_get_transport_store_protocol_name(proto), i++);
604 if (modest_account_mgr_account_exists (acc_mgr, name, TRUE))
614 on_apply (ModestAccountAssistant *self, gpointer user_data)
616 ModestAccountAssistantPrivate *priv;
617 ModestTransportStoreProtocol proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
618 ModestAuthProtocol security = MODEST_PROTOCOL_SECURITY_NONE;
619 ModestConnectionProtocol auth = MODEST_PROTOCOL_AUTH_NONE;
620 gchar *store_name, *transport_name;
621 const gchar *account_name, *username, *servername, *path;
622 ModestStoreWidget *store;
623 ModestTransportWidget *transport;
625 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
627 /* create server account -> store */
628 store = MODEST_STORE_WIDGET(priv->store_widget);
629 proto = modest_store_widget_get_proto (store);
630 username = modest_store_widget_get_username (store);
631 servername = modest_store_widget_get_servername (store);
632 path = modest_store_widget_get_path (store);
633 security = modest_store_widget_get_security (store);
634 auth = modest_store_widget_get_auth (store);
635 store_name = get_new_server_account_name (priv->account_mgr, proto,username, servername);
637 if (proto == MODEST_PROTOCOL_STORE_MAILDIR ||
638 proto == MODEST_PROTOCOL_STORE_MBOX) {
639 gchar *uri = get_account_uri (proto, path);
640 modest_account_mgr_add_server_account_uri (priv->account_mgr, store_name, proto, uri);
643 modest_account_mgr_add_server_account (priv->account_mgr, store_name, servername,
644 username, NULL, proto, security, auth);
646 /* create server account -> transport */
647 transport = MODEST_TRANSPORT_WIDGET(priv->transport_widget);
648 proto = modest_transport_widget_get_proto (transport);
651 if (proto == MODEST_PROTOCOL_TRANSPORT_SMTP) {
652 servername = modest_transport_widget_get_servername (transport);
653 if (modest_transport_widget_get_requires_auth (transport))
654 username = modest_transport_widget_get_username (transport);
657 transport_name = get_new_server_account_name (priv->account_mgr, proto,username, servername);
658 modest_account_mgr_add_server_account (priv->account_mgr,
659 transport_name, servername,
661 proto, security, auth);
664 account_name = get_account_name (self);
665 modest_account_mgr_add_account (priv->account_mgr,
668 transport_name, TRUE);
669 modest_account_mgr_set_string (priv->account_mgr,
671 MODEST_ACCOUNT_FULLNAME,
672 get_fullname(self), FALSE);
673 modest_account_mgr_set_string (priv->account_mgr,
675 MODEST_ACCOUNT_EMAIL,
676 get_email(self), FALSE);
680 g_free (transport_name);
686 modest_account_assistant_new (ModestAccountMgr *account_mgr)
689 ModestAccountAssistant *self;
690 ModestAccountAssistantPrivate *priv;
692 g_return_val_if_fail (account_mgr, NULL);
694 obj = g_object_new(MODEST_TYPE_ACCOUNT_ASSISTANT, NULL);
695 self = MODEST_ACCOUNT_ASSISTANT(obj);
697 priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
699 g_object_ref (account_mgr);
700 priv->account_mgr = account_mgr;
702 add_intro_page (self);
703 add_identity_page (self);
704 add_receiving_page (self);
705 add_sending_page (self);
706 add_final_page (self);
708 gtk_assistant_set_current_page (GTK_ASSISTANT(self), 0);
709 gtk_window_set_title (GTK_WINDOW(self),
710 _("Modest Account Wizard"));
711 gtk_window_set_resizable (GTK_WINDOW(self), TRUE);
712 gtk_window_set_default_size (GTK_WINDOW(self), 400, 400);
714 gtk_window_set_modal (GTK_WINDOW(self), TRUE);
716 g_signal_connect (G_OBJECT(self), "apply",
717 G_CALLBACK(on_apply), NULL);
718 g_signal_connect (G_OBJECT(self), "cancel",
719 G_CALLBACK(on_cancel), NULL);
720 g_signal_connect (G_OBJECT(self), "close",
721 G_CALLBACK(on_close), NULL);
723 return GTK_WIDGET(self);