diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4a215d33..eb3e1084 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -202,13 +202,19 @@ client/geary-config.vala
client/geary-controller.vala
client/main.vala
+client/accounts/account-dialog.vala
+client/accounts/account-dialog-account-list-pane.vala
+client/accounts/account-dialog-add-edit-pane.vala
+client/accounts/account-spinner-page.vala
+client/accounts/add-edit-page.vala
+client/accounts/login-dialog.vala
+
client/composer/composer-window.vala
client/composer/contact-entry-completion.vala
client/composer/email-entry.vala
client/composer/webview-edit-fixer.vala
client/dialogs/alert-dialog.vala
-client/dialogs/login-dialog.vala
client/dialogs/password-dialog.vala
client/dialogs/preferences-dialog.vala
diff --git a/src/client/accounts/account-dialog-account-list-pane.vala b/src/client/accounts/account-dialog-account-list-pane.vala
new file mode 100644
index 00000000..def829ec
--- /dev/null
+++ b/src/client/accounts/account-dialog-account-list-pane.vala
@@ -0,0 +1,95 @@
+/* Copyright 2013 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+// List of accounts. Used with AccountDialog.
+public class AccountDialogAccountListPane : Gtk.Box {
+ private Gtk.TreeView list_view;
+ private Gtk.ListStore list_model = new Gtk.ListStore(1, typeof (string));
+ private Gtk.ActionGroup actions;
+
+ public signal void add_account();
+
+ public signal void close();
+
+ public AccountDialogAccountListPane() {
+ Object(orientation: Gtk.Orientation.VERTICAL, spacing: 4);
+
+ Gtk.Builder builder = GearyApplication.instance.create_builder("account_list.glade");
+ pack_end((Gtk.Box) builder.get_object("container"));
+
+ list_view = (Gtk.TreeView) builder.get_object("account_list");
+ list_view.set_model(list_model);
+ list_view.insert_column_with_attributes (-1, "Account", new Gtk.CellRendererText (), "text", 0);
+ actions = (Gtk.ActionGroup) builder.get_object("account list actions");
+ actions.get_action("close").activate.connect(() => { close(); });
+ actions.get_action("add_account").activate.connect(() => { add_account(); });
+
+ // Theme hint: "join" the toolbar to the scrolled window above it.
+ Gtk.Toolbar toolbar = (Gtk.Toolbar) builder.get_object("toolbar");
+ Gtk.ScrolledWindow scroll = (Gtk.ScrolledWindow) builder.get_object("scrolledwindow");
+ toolbar.get_style_context().set_junction_sides(Gtk.JunctionSides.TOP);
+ scroll.get_style_context().set_junction_sides(Gtk.JunctionSides.BOTTOM);
+
+ // Add email accounts to the list.
+ try {
+ foreach (string address in Geary.Engine.instance.get_accounts().keys)
+ add_account_to_list(address);
+ } catch (Error e) {
+ debug("Error enumerating accounts: %s", e.message);
+ }
+
+ // Watch for accounts to be added/removed.
+ Geary.Engine.instance.account_added.connect(on_account_added);
+ Geary.Engine.instance.account_removed.connect(on_account_removed);
+ }
+
+ private void on_account_added(Geary.AccountInformation account) {
+ Gtk.TreeIter? iter = list_contains(account.email);
+ if (iter != null)
+ return; // Already listed.
+
+ add_account_to_list(account.email);
+ }
+
+ private void on_account_removed(Geary.AccountInformation account) {
+ remove_account_from_list(account.email);
+ }
+
+ // Adds an account to the list.
+ // Note: does NOT check if the account is already listed.
+ private void add_account_to_list(string address) {
+ Gtk.TreeIter iter;
+ list_model.append(out iter);
+ list_model.set(iter, 0, address);
+ }
+
+ // Removes an account on the list.
+ private void remove_account_from_list(string address) {
+ Gtk.TreeIter? iter = list_contains(address);
+ if (iter == null)
+ return;
+
+ list_model.remove(iter);
+ }
+
+ // Returns TreeIter of the address in the account list, else null.
+ private Gtk.TreeIter? list_contains(string address) {
+ Gtk.TreeIter iter;
+
+ if (!list_model.get_iter_first(out iter))
+ return null;
+
+ do {
+ string list_address = "";
+ list_model.get(iter, 0, out list_address);
+ if (list_address == address)
+ return iter;
+ } while (list_model.iter_next(ref iter));
+
+ return null;
+ }
+}
+
diff --git a/src/client/accounts/account-dialog-add-edit-pane.vala b/src/client/accounts/account-dialog-add-edit-pane.vala
new file mode 100644
index 00000000..6314cf48
--- /dev/null
+++ b/src/client/accounts/account-dialog-add-edit-pane.vala
@@ -0,0 +1,44 @@
+/* Copyright 2013 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+// Add or edit an account. Used with AccountDialog.
+public class AccountDialogAddEditPane : Gtk.Box {
+ public AddEditPage add_edit_page { get; private set; default = new AddEditPage(); }
+ private Gtk.ButtonBox button_box = new Gtk.ButtonBox(Gtk.Orientation.HORIZONTAL);
+ private Gtk.Button ok_button = new Gtk.Button.from_stock(Gtk.Stock.ADD);
+ private Gtk.Button cancel_button = new Gtk.Button.from_stock(Gtk.Stock.CANCEL);
+
+ public signal void ok(Geary.AccountInformation info);
+
+ public signal void cancel();
+
+ public signal void size_changed();
+
+ public AccountDialogAddEditPane() {
+ Object(orientation: Gtk.Orientation.VERTICAL, spacing: 4);
+
+ add_edit_page.show_welcome(false);
+ button_box.set_layout(Gtk.ButtonBoxStyle.END);
+ button_box.expand = false;
+ button_box.spacing = 6;
+ button_box.pack_start(cancel_button, false, false, 0);
+ button_box.pack_start(ok_button, false, false, 0);
+ ok_button.can_default = true;
+
+ ok_button.clicked.connect(on_ok);
+ cancel_button.clicked.connect(() => { cancel(); });
+
+ add_edit_page.size_changed.connect(() => { size_changed(); } );
+
+ pack_start(add_edit_page);
+ pack_start(button_box);
+ }
+
+ private void on_ok() {
+ ok(add_edit_page.get_account_information());
+ }
+}
+
diff --git a/src/client/accounts/account-dialog.vala b/src/client/accounts/account-dialog.vala
new file mode 100644
index 00000000..674845cd
--- /dev/null
+++ b/src/client/accounts/account-dialog.vala
@@ -0,0 +1,78 @@
+/* Copyright 2013 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+public class AccountDialog : Gtk.Dialog {
+ private const int MARGIN = 12;
+
+ private Gtk.Notebook notebook = new Gtk.Notebook();
+ private AccountDialogAccountListPane account_list_pane = new AccountDialogAccountListPane();
+ private AccountDialogAddEditPane add_edit_pane = new AccountDialogAddEditPane();
+ private AccountSpinnerPage spinner_pane = new AccountSpinnerPage();
+ private int add_edit_page_number;
+ private int account_list_page_number;
+ private int spinner_page_number;
+
+ public AccountDialog() {
+ set_size_request(450, -1); // Sets min size.
+ title = _("Accounts");
+ get_content_area().margin_top = MARGIN;
+ get_content_area().margin_left = MARGIN;
+ get_content_area().margin_right = MARGIN;
+
+ // Add pages to notebook.
+ account_list_page_number = notebook.append_page(account_list_pane, null);
+ add_edit_page_number = notebook.append_page(add_edit_pane, null);
+ spinner_page_number = notebook.append_page(spinner_pane, null);
+
+ // Connect signals from pages.
+ account_list_pane.close.connect(on_close);
+ account_list_pane.add_account.connect(on_add_account);
+ add_edit_pane.ok.connect(on_add_or_edit_account);
+ add_edit_pane.cancel.connect(on_cancel_add_edit);
+ add_edit_pane.size_changed.connect(() => { resize(1, 1); });
+
+ // Set default page.
+ notebook.set_current_page(account_list_page_number);
+
+ notebook.show_border = false;
+ notebook.show_tabs = false;
+ get_content_area().pack_start(notebook, true, true, 0);
+
+ notebook.show_all(); // Required due to longstanding Gtk.Notebook bug
+ }
+
+ private void on_close() {
+ response(Gtk.ResponseType.CLOSE);
+ }
+
+ private void on_add_account() {
+ notebook.set_current_page(add_edit_page_number);
+ }
+
+ private void on_add_or_edit_account(Geary.AccountInformation info) {
+ // TODO: Edit existing account.
+
+ // Show the busy spinner.
+ notebook.set_current_page(spinner_page_number);
+
+ // Validate account.
+ GearyApplication.instance.validate_async.begin(info, null, on_add_or_edit_account_completed);
+ }
+
+ private void on_add_or_edit_account_completed(Object? source, AsyncResult result) {
+ // If account was successfully added return to the account list. Otherwise, go back to the
+ // account add page so the user can try again.
+ if (GearyApplication.instance.validate_async.end(result))
+ notebook.set_current_page(account_list_page_number);
+ else
+ notebook.set_current_page(add_edit_page_number);
+ }
+
+ private void on_cancel_add_edit() {
+ notebook.set_current_page(account_list_page_number);
+ }
+}
+
diff --git a/src/client/accounts/account-spinner-page.vala b/src/client/accounts/account-spinner-page.vala
new file mode 100644
index 00000000..b5b2190a
--- /dev/null
+++ b/src/client/accounts/account-spinner-page.vala
@@ -0,0 +1,16 @@
+/* Copyright 2013 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+// Shows a simple spinner and a message indicating the account is being validated.
+public class AccountSpinnerPage : Gtk.Box {
+ public AccountSpinnerPage() {
+ Object(orientation: Gtk.Orientation.VERTICAL, spacing: 4);
+
+ Gtk.Builder builder = GearyApplication.instance.create_builder("account_spinner.glade");
+ pack_end((Gtk.Box) builder.get_object("container"));
+ }
+}
+
diff --git a/src/client/accounts/add-edit-page.vala b/src/client/accounts/add-edit-page.vala
new file mode 100644
index 00000000..b785b244
--- /dev/null
+++ b/src/client/accounts/add-edit-page.vala
@@ -0,0 +1,470 @@
+/* Copyright 2011-2013 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+// Page for adding or editing an account.
+public class AddEditPage : Gtk.Box {
+ public string real_name {
+ get { return entry_real_name.text; }
+ set { entry_real_name.text = value; }
+ }
+
+ public string email_address {
+ get { return entry_email.text; }
+ set { entry_email.text = value; }
+ }
+
+ public string password {
+ get { return entry_password.text; }
+ set { entry_password.text = value; }
+ }
+
+ public string imap_username {
+ get { return entry_imap_username.text; }
+ set { entry_imap_username.text = value; }
+ }
+
+ public string imap_password {
+ get { return entry_imap_password.text; }
+ set { entry_imap_password.text = value; }
+ }
+
+ public bool remember_password {
+ get { return check_remember_password.active; }
+ set { check_remember_password.active = value; }
+ }
+
+ public string smtp_username {
+ get { return entry_smtp_username.text; }
+ set { entry_smtp_username.text = value; }
+ }
+
+ public string smtp_password {
+ get { return entry_smtp_password.text; }
+ set { entry_smtp_password.text = value; }
+ }
+
+ public string imap_host {
+ get { return entry_imap_host.text; }
+ set { entry_imap_host.text = value; }
+ }
+
+ public uint16 imap_port {
+ get { return (uint16) int.parse(entry_imap_port.text.strip()); }
+ set { entry_imap_port.text = value.to_string(); }
+ }
+
+ public bool imap_ssl {
+ get { return combo_imap_encryption.active == Encryption.SSL; }
+ set {
+ if (value)
+ combo_imap_encryption.active = Encryption.SSL;
+ }
+ }
+
+ public bool imap_starttls {
+ get { return combo_imap_encryption.active == Encryption.STARTTLS; }
+ set {
+ if (value)
+ combo_imap_encryption.active = Encryption.STARTTLS;
+ }
+ }
+
+ public string smtp_host {
+ get { return entry_smtp_host.text; }
+ set { entry_smtp_host.text = value; }
+ }
+
+ public uint16 smtp_port {
+ get { return (uint16) int.parse(entry_smtp_port.text.strip()); }
+ set { entry_smtp_port.text = value.to_string(); }
+ }
+
+ public bool smtp_ssl {
+ get { return combo_smtp_encryption.active == Encryption.SSL; }
+ set {
+ if (value)
+ combo_smtp_encryption.active = Encryption.SSL;
+ }
+ }
+
+ public bool smtp_starttls {
+ get { return combo_smtp_encryption.active == Encryption.STARTTLS; }
+ set {
+ if (value)
+ combo_smtp_encryption.active = Encryption.STARTTLS;
+ }
+ }
+
+ // these are tied to the values in the Glade file
+ private enum Encryption {
+ NONE = 0,
+ SSL = 1,
+ STARTTLS = 2
+ }
+
+ private bool welcome_mode = true;
+
+ private Gtk.Widget container_widget;
+ private Gtk.Box welcome_box;
+
+ private Gtk.Entry entry_email;
+ private Gtk.Label label_password;
+ private Gtk.Entry entry_password;
+ private Gtk.Entry entry_real_name;
+ private Gtk.ComboBoxText combo_service;
+ private Gtk.CheckButton check_remember_password;
+
+ private Gtk.Alignment other_info;
+
+ // IMAP info widgets
+ private Gtk.Entry entry_imap_host;
+ private Gtk.Entry entry_imap_port;
+ private Gtk.Entry entry_imap_username;
+ private Gtk.Entry entry_imap_password;
+ private Gtk.ComboBox combo_imap_encryption;
+
+ // SMTP info widgets
+ private Gtk.Entry entry_smtp_host;
+ private Gtk.Entry entry_smtp_port;
+ private Gtk.Entry entry_smtp_username;
+ private Gtk.Entry entry_smtp_password;
+ private Gtk.ComboBox combo_smtp_encryption;
+
+ private bool edited_imap_port = false;
+ private bool edited_smtp_port = false;
+
+ public signal void info_changed();
+
+ public signal void size_changed();
+
+ public AddEditPage() {
+ Object(orientation: Gtk.Orientation.VERTICAL, spacing: 4);
+
+ Gtk.Builder builder = GearyApplication.instance.create_builder("login.glade");
+
+ // Primary container.
+ container_widget = (Gtk.Widget) builder.get_object("container");
+ pack_start(container_widget);
+
+ welcome_box = (Gtk.Box) builder.get_object("welcome_box");
+ Gtk.Label label_welcome = (Gtk.Label) builder.get_object("label-welcome");
+ label_welcome.set_markup("%s\n%s".printf(
+ _("Welcome to Geary."), _("Enter your account information to get started.")));
+
+ entry_real_name = (Gtk.Entry) builder.get_object("entry: real_name");
+ combo_service = (Gtk.ComboBoxText) builder.get_object("combo: service");
+ entry_email = (Gtk.Entry) builder.get_object("entry: email");
+ label_password = (Gtk.Label) builder.get_object("label: password");
+ entry_password = (Gtk.Entry) builder.get_object("entry: password");
+ check_remember_password = (Gtk.CheckButton) builder.get_object("check: remember_password");
+
+ other_info = (Gtk.Alignment) builder.get_object("container: other_info");
+
+ // IMAP info widgets.
+ entry_imap_host = (Gtk.Entry) builder.get_object("entry: imap host");
+ entry_imap_port = (Gtk.Entry) builder.get_object("entry: imap port");
+ entry_imap_username = (Gtk.Entry) builder.get_object("entry: imap username");
+ entry_imap_password = (Gtk.Entry) builder.get_object("entry: imap password");
+ combo_imap_encryption = (Gtk.ComboBox) builder.get_object("combo: imap encryption");
+
+ // SMTP info widgets.
+ entry_smtp_host = (Gtk.Entry) builder.get_object("entry: smtp host");
+ entry_smtp_port = (Gtk.Entry) builder.get_object("entry: smtp port");
+ entry_smtp_username = (Gtk.Entry) builder.get_object("entry: smtp username");
+ entry_smtp_password = (Gtk.Entry) builder.get_object("entry: smtp password");
+ combo_smtp_encryption = (Gtk.ComboBox) builder.get_object("combo: smtp encryption");
+
+ // Build list of service providers.
+ foreach (Geary.ServiceProvider p in Geary.ServiceProvider.get_providers())
+ combo_service.append_text(p.display_name());
+
+ // Set defaults.
+ set_service_provider(Geary.ServiceProvider.GMAIL);
+ imap_ssl = true;
+ smtp_ssl = true;
+
+ combo_service.changed.connect(update_ui);
+ entry_email.changed.connect(on_changed);
+ entry_password.changed.connect(on_changed);
+ entry_real_name.changed.connect(on_changed);
+ check_remember_password.toggled.connect(on_changed);
+ combo_service.changed.connect(on_changed);
+ entry_imap_host.changed.connect(on_changed);
+ entry_imap_port.changed.connect(on_changed);
+ entry_imap_username.changed.connect(on_changed);
+ entry_imap_password.changed.connect(on_changed);
+ entry_smtp_host.changed.connect(on_changed);
+ entry_smtp_port.changed.connect(on_changed);
+ entry_smtp_username.changed.connect(on_changed);
+ entry_smtp_password.changed.connect(on_changed);
+
+ entry_email.changed.connect(on_email_changed);
+ entry_password.changed.connect(on_password_changed);
+
+ combo_imap_encryption.changed.connect(on_imap_encryption_changed);
+ combo_smtp_encryption.changed.connect(on_smtp_encryption_changed);
+
+ entry_imap_port.insert_text.connect(on_port_insert_text);
+ entry_smtp_port.insert_text.connect(on_port_insert_text);
+
+ // Shows/hides settings.
+ update_ui();
+ }
+
+ public void set_all_info(
+ string? initial_real_name = null,
+ string? initial_email = null,
+ string? initial_imap_username = null,
+ string? initial_imap_password = null,
+ bool initial_remember_password = true,
+ string? initial_smtp_username = null,
+ string? initial_smtp_password = null,
+ int initial_service_provider = -1,
+ string? initial_default_imap_host = null,
+ uint16 initial_default_imap_port = Geary.Imap.ClientConnection.DEFAULT_PORT_SSL,
+ bool initial_default_imap_ssl = true,
+ bool initial_default_imap_starttls = false,
+ string? initial_default_smtp_host = null,
+ uint16 initial_default_smtp_port = Geary.Smtp.ClientConnection.DEFAULT_PORT_SSL,
+ bool initial_default_smtp_ssl = true,
+ bool initial_default_smtp_starttls = false) {
+
+ // Set defaults (other than service provider, which is set above)
+ real_name = initial_real_name ?? "";
+ email_address = initial_email ?? "";
+ bool use_imap_password = initial_imap_password == initial_smtp_password &&
+ initial_imap_password != null;
+ password = use_imap_password ? initial_imap_password : "";
+ remember_password = initial_remember_password;
+
+ // Set defaults for IMAP info
+ imap_host = initial_default_imap_host ?? "";
+ imap_port = initial_default_imap_port;
+ imap_username = initial_imap_username ?? "";
+ imap_password = initial_imap_password ?? "";
+ imap_ssl = initial_default_imap_ssl;
+ imap_starttls = initial_default_imap_starttls;
+
+ // Set defaults for SMTP info
+ smtp_host = initial_default_smtp_host ?? "";
+ smtp_port = initial_default_smtp_port;
+ smtp_username = initial_smtp_username ?? "";
+ smtp_password = initial_smtp_password ?? "";
+ imap_ssl = initial_default_imap_ssl;
+ imap_starttls = initial_default_imap_starttls;
+
+ if (Geary.String.is_empty(real_name))
+ entry_real_name.grab_focus();
+ else
+ entry_email.grab_focus();
+ }
+
+ // Puts this page into welcome mode which shows the "Welcome to Geary" message, etc.
+ // Default is true.
+ public void show_welcome(bool welcome) {
+ welcome_mode = welcome;
+ update_ui();
+ }
+
+ // TODO: Only reset if not manually set by user.
+ private void on_email_changed() {
+ entry_imap_username.text = entry_email.text;
+ entry_smtp_username.text = entry_email.text;
+ }
+
+ // TODO: Only reset if not manually set by user.
+ private void on_password_changed() {
+ entry_imap_password.text = entry_password.text;
+ entry_smtp_password.text = entry_password.text;
+ }
+
+ private void on_changed() {
+ info_changed();
+ }
+
+ private void on_port_insert_text(Gtk.Editable e, string text, int length, ref int position) {
+ // Prevent non-numerical characters and ensure port is <= uint16.MAX
+ if (!uint64.try_parse(text) || uint64.parse(((Gtk.Entry) e).text) > uint16.MAX) {
+ Signal.stop_emission_by_name(e, "insert-text");
+ } else {
+ if (e == entry_imap_port)
+ edited_imap_port = true;
+ else if (e == entry_smtp_port)
+ edited_smtp_port = true;
+ }
+ }
+
+ private void on_imap_encryption_changed() {
+ if (edited_imap_port)
+ return;
+
+ imap_port = get_default_imap_port();
+ edited_imap_port = false;
+ }
+
+ private uint16 get_default_imap_port() {
+ switch (combo_imap_encryption.active) {
+ case Encryption.SSL:
+ return Geary.Imap.ClientConnection.DEFAULT_PORT_SSL;
+
+ case Encryption.NONE:
+ case Encryption.STARTTLS:
+ default:
+ return Geary.Imap.ClientConnection.DEFAULT_PORT;
+ }
+ }
+
+ private void on_smtp_encryption_changed() {
+ if (edited_smtp_port)
+ return;
+
+ smtp_port = get_default_smtp_port();
+ edited_smtp_port = false;
+ }
+
+ private uint16 get_default_smtp_port() {
+ switch (combo_smtp_encryption.active) {
+ case Encryption.SSL:
+ return Geary.Smtp.ClientConnection.DEFAULT_PORT_SSL;
+
+ case Encryption.STARTTLS:
+ return Geary.Smtp.ClientConnection.DEFAULT_PORT_STARTTLS;
+
+ case Encryption.NONE:
+ default:
+ return Geary.Smtp.ClientConnection.DEFAULT_PORT;
+ }
+ }
+
+ public bool is_complete() {
+ switch (get_service_provider()) {
+ case Geary.ServiceProvider.OTHER:
+ if (Geary.String.is_empty_or_whitespace(email_address) ||
+ Geary.String.is_empty_or_whitespace(imap_host) ||
+ Geary.String.is_empty_or_whitespace(imap_port.to_string()) ||
+ Geary.String.is_empty_or_whitespace(imap_username) ||
+ Geary.String.is_empty_or_whitespace(imap_password) ||
+ Geary.String.is_empty_or_whitespace(smtp_host) ||
+ Geary.String.is_empty_or_whitespace(smtp_port.to_string()) ||
+ Geary.String.is_empty_or_whitespace(smtp_username) ||
+ Geary.String.is_empty_or_whitespace(smtp_password))
+ return false;
+ break;
+
+ // GMAIL and YAHOO
+ default:
+ if (Geary.String.is_empty_or_whitespace(email_address) ||
+ Geary.String.is_empty_or_whitespace(password))
+ return false;
+ break;
+ }
+
+ return true;
+ }
+
+ public Geary.AccountInformation? get_account_information() {
+ Geary.AccountInformation account_information;
+
+ Geary.Credentials imap_credentials = new Geary.Credentials(imap_username.strip(), imap_password.strip());
+ Geary.Credentials smtp_credentials = new Geary.Credentials(smtp_username.strip(), smtp_password.strip());
+
+ try {
+ account_information = Geary.Engine.instance.get_accounts().get(email_address);
+ if (account_information == null)
+ account_information = Geary.Engine.instance.create_orphan_account(email_address);
+ } catch (Error err) {
+ debug("Unable to open account information for %s: %s", email_address, err.message);
+
+ return null;
+ }
+
+ account_information.real_name = real_name.strip();
+ account_information.imap_credentials = imap_credentials;
+ account_information.smtp_credentials = smtp_credentials;
+ account_information.imap_remember_password = remember_password;
+ account_information.smtp_remember_password = remember_password;
+ account_information.service_provider = get_service_provider();
+ account_information.default_imap_server_host = imap_host;
+ account_information.default_imap_server_port = imap_port;
+ account_information.default_imap_server_ssl = imap_ssl;
+ account_information.default_imap_server_starttls = imap_starttls;
+ account_information.default_smtp_server_host = smtp_host.strip();
+ account_information.default_smtp_server_port = smtp_port;
+ account_information.default_smtp_server_ssl = smtp_ssl;
+ account_information.default_smtp_server_starttls = smtp_starttls;
+
+ on_changed();
+
+ return account_information;
+ }
+
+ // Updates UI based on various options.
+ private void update_ui() {
+ base.show_all();
+ welcome_box.visible = welcome_mode;
+
+ if (get_service_provider() == Geary.ServiceProvider.OTHER) {
+ // Display all options for custom providers.
+ label_password.hide();
+ entry_password.hide();
+ other_info.show();
+ set_other_info_sensitive(true);
+ } else {
+ // For special-cased providers, only display necessary info.
+ label_password.show();
+ entry_password.show();
+ other_info.hide();
+
+ // TODO: Will be used by upcoming edit mode to display greyed-out other info.
+ set_other_info_sensitive(welcome_mode);
+
+ // For supported providers, fill out the rest of the form automagically.
+ imap_username = email_address;
+ smtp_username = email_address;
+ imap_password = password;
+ smtp_password = password;
+ }
+
+ size_changed();
+ }
+
+ public Geary.ServiceProvider get_service_provider() {
+ return (Geary.ServiceProvider) combo_service.get_active();
+ }
+
+ public void set_service_provider(Geary.ServiceProvider provider) {
+ foreach (Geary.ServiceProvider p in Geary.ServiceProvider.get_providers()) {
+ if (p == provider)
+ combo_service.set_active(p);
+ }
+
+ if (combo_service.get_active() == -1)
+ combo_service.set_active(0);
+ }
+
+ // Greys out "other info" (server settings, etc.)
+ public void set_other_info_sensitive(bool sensitive) {
+ entry_imap_host.sensitive = sensitive;
+ entry_imap_port.sensitive = sensitive;
+ entry_imap_username.sensitive = sensitive;
+ entry_imap_password.sensitive = sensitive;
+ combo_imap_encryption.sensitive = sensitive;
+
+ entry_smtp_host.sensitive = sensitive;
+ entry_smtp_port.sensitive = sensitive;
+ entry_smtp_username.sensitive = sensitive;
+ entry_smtp_password.sensitive = sensitive;
+ combo_smtp_encryption.sensitive = sensitive;
+ }
+
+ // Since users of this class embed it in a Gtk.Notebook, we're forced to override this method
+ // to prevent hidden UI elements from appearing.
+ public override void show_all() {
+ // Note that update_ui() calls base.show_all(), so no need to do that here.
+ update_ui();
+ }
+}
+
diff --git a/src/client/accounts/login-dialog.vala b/src/client/accounts/login-dialog.vala
new file mode 100644
index 00000000..d41f816b
--- /dev/null
+++ b/src/client/accounts/login-dialog.vala
@@ -0,0 +1,85 @@
+/* Copyright 2011-2013 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+// Displays a dialog for collecting the user's login data.
+public class LoginDialog : Gtk.Dialog {
+ private Gtk.Button ok_button;
+ private Gtk.Button cancel_button;
+ private AddEditPage page = new AddEditPage();
+ private AccountSpinnerPage spinner_page = new AccountSpinnerPage();
+
+ public LoginDialog() {
+ Object();
+ set_type_hint(Gdk.WindowTypeHint.DIALOG);
+ set_size_request(450, -1); // Sets min width.
+
+ page.margin = 5;
+ spinner_page.margin = 5;
+ get_content_area().pack_start(page, true, true, 0);
+ get_content_area().pack_start(spinner_page, true, true, 0);
+ spinner_page.visible = false;
+ page.size_changed.connect(() => { resize(1, 1); });
+ page.info_changed.connect(on_info_changed);
+
+ cancel_button = new Gtk.Button.from_stock(Gtk.Stock.CANCEL);
+ add_action_widget(cancel_button, Gtk.ResponseType.CANCEL);
+ ok_button = new Gtk.Button.from_stock(Gtk.Stock.ADD);
+ ok_button.can_default = true;
+ add_action_widget(ok_button, Gtk.ResponseType.OK);
+ set_default_response(Gtk.ResponseType.OK);
+ get_action_area().show_all();
+
+ on_info_changed();
+ }
+
+ public LoginDialog.from_account_information(Geary.AccountInformation initial_account_information) {
+ this();
+ set_account_information(initial_account_information);
+ }
+
+ public void set_real_name(string name) {
+ page.real_name = name;
+ }
+
+ public void set_account_information(Geary.AccountInformation info) {
+ page.set_all_info(info.real_name,
+ info.email,
+ info.imap_credentials.user,
+ info.imap_credentials.pass,
+ info.imap_remember_password && info.smtp_remember_password,
+ info.smtp_credentials.user,
+ info.smtp_credentials.pass,
+ info.service_provider,
+ info.default_imap_server_host,
+ info.default_imap_server_port,
+ info.default_imap_server_ssl,
+ info.default_imap_server_starttls,
+ info.default_smtp_server_host,
+ info.default_smtp_server_port,
+ info.default_smtp_server_ssl,
+ info.default_smtp_server_starttls);
+ }
+
+ public Geary.AccountInformation get_account_information() {
+ return page.get_account_information();
+ }
+
+ private void on_info_changed() {
+ if (!spinner_page.visible)
+ ok_button.sensitive = page.is_complete();
+ else
+ ok_button.sensitive = false;
+ }
+
+ // Switches between the account page and the busy spinner.
+ public void show_spinner(bool visible) {
+ spinner_page.visible = visible;
+ page.visible = !visible;
+ cancel_button.sensitive = !visible;
+ on_info_changed(); // sets OK button sensitivity
+ }
+}
+
diff --git a/src/client/dialogs/login-dialog.vala b/src/client/dialogs/login-dialog.vala
deleted file mode 100644
index bb68416c..00000000
--- a/src/client/dialogs/login-dialog.vala
+++ /dev/null
@@ -1,376 +0,0 @@
-/* Copyright 2011-2012 Yorba Foundation
- *
- * This software is licensed under the GNU Lesser General Public License
- * (version 2.1 or later). See the COPYING file in this distribution.
- */
-
-// Displays a dialog for collecting the user's login data.
-public class LoginDialog {
- // these are tied to the values in the Glade file
- private enum Encryption {
- NONE = 0,
- SSL = 1,
- STARTTLS = 2
- }
-
- private Gtk.Dialog dialog;
- private Gtk.Entry entry_email;
- private Gtk.Label label_password;
- private Gtk.Entry entry_password;
- private Gtk.Entry entry_real_name;
- private Gtk.ComboBoxText combo_service;
- private Gtk.CheckButton check_remember_password;
-
- private Gtk.Alignment other_info;
-
- // IMAP info widgets
- private Gtk.Entry entry_imap_host;
- private Gtk.Entry entry_imap_port;
- private Gtk.Entry entry_imap_username;
- private Gtk.Entry entry_imap_password;
- private Gtk.ComboBox combo_imap_encryption;
-
- // SMTP info widgets
- private Gtk.Entry entry_smtp_host;
- private Gtk.Entry entry_smtp_port;
- private Gtk.Entry entry_smtp_username;
- private Gtk.Entry entry_smtp_password;
- private Gtk.ComboBox combo_smtp_encryption;
-
- private Gtk.Button ok_button;
-
- private bool edited_imap_port = false;
- private bool edited_smtp_port = false;
-
- public Geary.AccountInformation account_information { get; private set; }
-
- // TODO: Update the login dialog to use email, imap_credentials, smtp_credentials,
- // imap_remember_password, and smtp_remember_password.
- public LoginDialog.from_account_information(Geary.AccountInformation initial_account_information) {
- this(initial_account_information.real_name,
- initial_account_information.email,
- initial_account_information.imap_credentials.user,
- initial_account_information.imap_credentials.pass,
- initial_account_information.imap_remember_password && initial_account_information.smtp_remember_password,
- initial_account_information.smtp_credentials.user,
- initial_account_information.smtp_credentials.pass,
- initial_account_information.service_provider,
- initial_account_information.default_imap_server_host,
- initial_account_information.default_imap_server_port,
- initial_account_information.default_imap_server_ssl,
- initial_account_information.default_imap_server_starttls,
- initial_account_information.default_smtp_server_host,
- initial_account_information.default_smtp_server_port,
- initial_account_information.default_smtp_server_ssl,
- initial_account_information.default_smtp_server_starttls);
- }
-
- public LoginDialog(
- string? initial_real_name = null,
- string? initial_email = null,
- string? initial_imap_username = null,
- string? initial_imap_password = null,
- bool initial_remember_password = true,
- string? initial_smtp_username = null,
- string? initial_smtp_password = null,
- int initial_service_provider = -1,
- string? initial_default_imap_host = null,
- uint16 initial_default_imap_port = Geary.Imap.ClientConnection.DEFAULT_PORT_SSL,
- bool initial_default_imap_ssl = true,
- bool initial_default_imap_starttls = false,
- string? initial_default_smtp_host = null,
- uint16 initial_default_smtp_port = Geary.Smtp.ClientConnection.DEFAULT_PORT_SSL,
- bool initial_default_smtp_ssl = true,
- bool initial_default_smtp_starttls = false) {
- Gtk.Builder builder = GearyApplication.instance.create_builder("login.glade");
-
- dialog = builder.get_object("LoginDialog") as Gtk.Dialog;
- dialog.set_type_hint(Gdk.WindowTypeHint.DIALOG);
- dialog.set_default_response(Gtk.ResponseType.OK);
-
- Gtk.Label label_welcome = (Gtk.Label) builder.get_object("label-welcome");
- label_welcome.set_markup("%s\n%s".printf(
- _("Welcome to Geary."), _("Enter your account information to get started.")));
-
- entry_real_name = builder.get_object("entry: real_name") as Gtk.Entry;
- combo_service = builder.get_object("combo: service") as Gtk.ComboBoxText;
- entry_email = builder.get_object("entry: email") as Gtk.Entry;
- label_password = builder.get_object("label: password") as Gtk.Label;
- entry_password = builder.get_object("entry: password") as Gtk.Entry;
- check_remember_password = builder.get_object("check: remember_password") as Gtk.CheckButton;
-
- other_info = builder.get_object("container: other_info") as Gtk.Alignment;
-
- // IMAP info widgets.
- entry_imap_host = builder.get_object("entry: imap host") as Gtk.Entry;
- entry_imap_port = builder.get_object("entry: imap port") as Gtk.Entry;
- entry_imap_username = builder.get_object("entry: imap username") as Gtk.Entry;
- entry_imap_password = builder.get_object("entry: imap password") as Gtk.Entry;
- combo_imap_encryption = builder.get_object("combo: imap encryption") as Gtk.ComboBox;
-
- // SMTP info widgets.
- entry_smtp_host = builder.get_object("entry: smtp host") as Gtk.Entry;
- entry_smtp_port = builder.get_object("entry: smtp port") as Gtk.Entry;
- entry_smtp_username = builder.get_object("entry: smtp username") as Gtk.Entry;
- entry_smtp_password = builder.get_object("entry: smtp password") as Gtk.Entry;
- combo_smtp_encryption = builder.get_object("combo: smtp encryption") as Gtk.ComboBox;
-
- combo_service.changed.connect(on_service_changed);
-
- foreach (Geary.ServiceProvider p in Geary.ServiceProvider.get_providers()) {
- combo_service.append_text(p.display_name());
- if (p == initial_service_provider)
- combo_service.set_active(p);
- }
-
- if (combo_service.get_active() == -1)
- combo_service.set_active(0);
-
- // Set defaults (other than service provider, which is set above)
- entry_real_name.set_text(initial_real_name ?? "");
- entry_email.set_text(initial_email ?? "");
- bool use_imap_password = initial_imap_password == initial_smtp_password &&
- initial_imap_password != null;
- entry_password.set_text(use_imap_password ? initial_imap_password : "");
- check_remember_password.active = initial_remember_password;
-
- // Set defaults for IMAP info
- entry_imap_host.set_text(initial_default_imap_host ?? "");
- entry_imap_port.set_text(initial_default_imap_port.to_string());
- entry_imap_username.set_text(initial_imap_username ?? "");
- entry_imap_password.set_text(initial_imap_password ?? "");
- if (initial_default_imap_ssl)
- combo_imap_encryption.active = Encryption.SSL;
- else if (initial_default_imap_starttls)
- combo_imap_encryption.active = Encryption.STARTTLS;
- else
- combo_imap_encryption.active = Encryption.NONE;
-
- // Set defaults for SMTP info
- entry_smtp_host.set_text(initial_default_smtp_host ?? "");
- entry_smtp_port.set_text(initial_default_smtp_port.to_string());
- entry_smtp_username.set_text(initial_smtp_username ?? "");
- entry_smtp_password.set_text(initial_smtp_password ?? "");
- if (initial_default_smtp_ssl)
- combo_smtp_encryption.active = Encryption.SSL;
- else if (initial_default_smtp_starttls)
- combo_smtp_encryption.active = Encryption.STARTTLS;
- else
- combo_smtp_encryption.active = Encryption.NONE;
-
- if (Geary.String.is_empty(entry_real_name.text))
- entry_real_name.grab_focus();
- else
- entry_email.grab_focus();
-
- entry_email.changed.connect(on_changed);
- entry_password.changed.connect(on_changed);
- entry_real_name.changed.connect(on_changed);
- check_remember_password.toggled.connect(on_changed);
- combo_service.changed.connect(on_changed);
- entry_imap_host.changed.connect(on_changed);
- entry_imap_port.changed.connect(on_changed);
- entry_imap_username.changed.connect(on_changed);
- entry_imap_password.changed.connect(on_changed);
- entry_smtp_host.changed.connect(on_changed);
- entry_smtp_port.changed.connect(on_changed);
- entry_smtp_username.changed.connect(on_changed);
- entry_smtp_password.changed.connect(on_changed);
-
- entry_email.changed.connect(on_email_changed);
- entry_password.changed.connect(on_password_changed);
-
- combo_imap_encryption.changed.connect(on_imap_encryption_changed);
- combo_smtp_encryption.changed.connect(on_smtp_encryption_changed);
-
- entry_imap_port.insert_text.connect(on_port_insert_text);
- entry_smtp_port.insert_text.connect(on_port_insert_text);
-
- dialog.add_action_widget(new Gtk.Button.from_stock(Gtk.Stock.CANCEL), Gtk.ResponseType.CANCEL);
- ok_button = new Gtk.Button.from_stock(Gtk.Stock.OK);
- ok_button.can_default = true;
- ok_button.sensitive = is_complete();
- dialog.add_action_widget(ok_button, Gtk.ResponseType.OK);
- dialog.set_default_response(Gtk.ResponseType.OK);
- }
-
- // Runs the dialog.
- public bool show() {
- dialog.show();
- dialog.get_action_area().show_all();
- on_service_changed(); // shows/hides server settings
-
- Gtk.ResponseType response = (Gtk.ResponseType) dialog.run();
- if (response != Gtk.ResponseType.OK)
- return false;
-
- bool use_extra_info = get_service_provider() == Geary.ServiceProvider.OTHER;
-
- string email = entry_email.text.strip();
- string imap_username = use_extra_info ? entry_imap_username.text.strip() : email;
- string imap_password = (use_extra_info ? entry_imap_password : entry_password).text.strip();
- bool imap_remember_password = check_remember_password.active;
- Geary.Credentials imap_credentials = new Geary.Credentials(imap_username, imap_password);
-
- string smtp_username = use_extra_info ? entry_smtp_username.text.strip() : email;
- string smtp_password = (use_extra_info ? entry_smtp_password : entry_password).text.strip();
- bool smtp_remember_password = check_remember_password.active;
- Geary.Credentials smtp_credentials = new Geary.Credentials(smtp_username, smtp_password);
-
- try {
- account_information = Geary.Engine.instance.get_accounts().get(email);
- if (account_information == null)
- account_information = Geary.Engine.instance.create_orphan_account(email);
- } catch (Error err) {
- debug("Unable to open account information for %s: %s", email, err.message);
-
- return false;
- }
-
- account_information.real_name = entry_real_name.text.strip();
- account_information.imap_credentials = imap_credentials;
- account_information.smtp_credentials = smtp_credentials;
- account_information.imap_remember_password = imap_remember_password;
- account_information.smtp_remember_password = smtp_remember_password;
- account_information.service_provider = get_service_provider();
- account_information.default_imap_server_host = entry_imap_host.text.strip();
- account_information.default_imap_server_port = (uint16) int.parse(entry_imap_port.text.strip());
- account_information.default_imap_server_ssl = (combo_imap_encryption.active == Encryption.SSL);
- account_information.default_imap_server_starttls = (combo_imap_encryption.active == Encryption.STARTTLS);
- account_information.default_smtp_server_host = entry_smtp_host.text.strip();
- account_information.default_smtp_server_port = (uint16) int.parse(entry_smtp_port.text.strip());
- account_information.default_smtp_server_ssl = (combo_smtp_encryption.active == Encryption.SSL);
- account_information.default_smtp_server_starttls = (combo_smtp_encryption.active == Encryption.STARTTLS);
-
- on_changed();
-
- dialog.destroy();
- return true;
- }
-
- // TODO: Only reset if not manually set by user.
- private void on_email_changed() {
- entry_imap_username.text = entry_email.text;
- entry_smtp_username.text = entry_email.text;
- }
-
- // TODO: Only reset if not manually set by user.
- private void on_password_changed() {
- entry_imap_password.text = entry_password.text;
- entry_smtp_password.text = entry_password.text;
- }
-
- private void on_service_changed() {
- if (get_service_provider() == Geary.ServiceProvider.OTHER) {
- label_password.hide();
- entry_password.hide();
- check_remember_password.label = _("Re_member passwords");
- other_info.show();
- } else {
- label_password.show();
- entry_password.show();
- check_remember_password.label = _("Re_member password");
- other_info.hide();
- dialog.resize(1, 1);
- }
- }
-
- private void on_changed() {
- ok_button.sensitive = is_complete();
- }
-
- private void on_port_insert_text(Gtk.Editable e, string text, int length, ref int position) {
- // Prevent non-numerical characters and ensure port is <= uint16.MAX
- if (!uint64.try_parse(text) || uint64.parse(((Gtk.Entry) e).text) > uint16.MAX) {
- Signal.stop_emission_by_name(e, "insert-text");
- } else {
- if (e == entry_imap_port)
- edited_imap_port = true;
- else if (e == entry_smtp_port)
- edited_smtp_port = true;
- }
- }
-
- private void on_imap_encryption_changed() {
- if (edited_imap_port)
- return;
-
- entry_imap_port.text = get_default_imap_port().to_string();
- edited_imap_port = false;
- }
-
- private uint16 get_default_imap_port() {
- switch (combo_imap_encryption.active) {
- case Encryption.SSL:
- return Geary.Imap.ClientConnection.DEFAULT_PORT_SSL;
-
- case Encryption.NONE:
- case Encryption.STARTTLS:
- default:
- return Geary.Imap.ClientConnection.DEFAULT_PORT;
- }
- }
-
- private void on_smtp_encryption_changed() {
- if (edited_smtp_port)
- return;
-
- entry_smtp_port.text = get_default_smtp_port().to_string();
- edited_smtp_port = false;
- }
-
- private uint16 get_default_smtp_port() {
- switch (combo_smtp_encryption.active) {
- case Encryption.SSL:
- return Geary.Smtp.ClientConnection.DEFAULT_PORT_SSL;
-
- case Encryption.STARTTLS:
- return Geary.Smtp.ClientConnection.DEFAULT_PORT_STARTTLS;
-
- case Encryption.NONE:
- default:
- return Geary.Smtp.ClientConnection.DEFAULT_PORT;
- }
- }
-
- private Geary.ServiceProvider get_service_provider() {
- return (Geary.ServiceProvider) combo_service.get_active();
- }
-
- private bool is_valid_port(string text) {
- uint64 port;
- if (!uint64.try_parse(text, out port))
- return false;
-
- return (port <= uint16.MAX);
- }
-
- private bool is_complete() {
- switch (get_service_provider()) {
- case Geary.ServiceProvider.OTHER:
- if (Geary.String.is_empty_or_whitespace(entry_email.text) ||
- Geary.String.is_empty_or_whitespace(entry_imap_host.text) ||
- Geary.String.is_empty_or_whitespace(entry_imap_port.text) ||
- Geary.String.is_empty_or_whitespace(entry_imap_username.text) ||
- Geary.String.is_empty_or_whitespace(entry_imap_password.text) ||
- Geary.String.is_empty_or_whitespace(entry_smtp_host.text) ||
- Geary.String.is_empty_or_whitespace(entry_smtp_port.text) ||
- Geary.String.is_empty_or_whitespace(entry_smtp_username.text) ||
- Geary.String.is_empty_or_whitespace(entry_smtp_password.text) ||
- !is_valid_port(entry_imap_port.text) ||
- !is_valid_port(entry_smtp_port.text))
- return false;
- break;
-
- // GMAIL and YAHOO
- default:
- if (Geary.String.is_empty_or_whitespace(entry_email.text) ||
- Geary.String.is_empty_or_whitespace(entry_password.text))
- return false;
- break;
- }
-
- return true;
- }
-}
-
diff --git a/src/client/geary-application.vala b/src/client/geary-application.vala
index f2b3672b..dcee879f 100644
--- a/src/client/geary-application.vala
+++ b/src/client/geary-application.vala
@@ -81,6 +81,8 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
private GearyController? controller = null;
private Geary.Account? account = null;
+ private LoginDialog? login_dialog = null;
+
private File exec_dir;
public GearyApplication() {
@@ -193,33 +195,19 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
Cancellable? cancellable = null) {
Geary.AccountInformation? result = account_information;
do {
- result = yield validate_async(result, cancellable);
+ result = yield validate_or_retry_async(result, cancellable);
} while (result != null);
+
+ if (login_dialog != null)
+ login_dialog.hide();
}
-
+
// Returns null if we are done validating, or the revised account information if we should retry.
- private async Geary.AccountInformation? validate_async(Geary.AccountInformation account_information,
+ private async Geary.AccountInformation? validate_or_retry_async(Geary.AccountInformation account_information,
Cancellable? cancellable = null) {
- bool success = false;
- try {
- success = yield account_information.validate_async(cancellable);
- } catch (Geary.EngineError err) {
- debug("Error validating account: %s", err.message);
- success = false;
- }
+ if (yield validate_async(account_information, cancellable))
+ return null;
- if (success) {
- account_information.store_async.begin(cancellable);
-
- try {
- set_account(account_information.get_account());
- debug("Successfully validated account information");
- return null;
- } catch (Geary.EngineError err) {
- debug("Unable to retrieve email account: %s", err.message);
- }
- }
-
debug("Validation failed. Prompting user for revised account information");
Geary.AccountInformation? new_account_information =
request_account_information(account_information);
@@ -238,6 +226,34 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
return new_account_information;
}
+ // Attempts to validate and add an account. Returns true on success, else false.
+ public async bool validate_async(Geary.AccountInformation account_information,
+ Cancellable? cancellable = null) {
+ bool success = false;
+ try {
+ success = yield account_information.validate_async(cancellable);
+ } catch (Geary.EngineError err) {
+ debug("Error validating account: %s", err.message);
+
+ return false;
+ }
+
+ if (success) {
+ account_information.store_async.begin(cancellable);
+
+ try {
+ set_account(account_information.get_account());
+ debug("Successfully validated account information");
+
+ return true;
+ } catch (Geary.EngineError err) {
+ debug("Unable to retrieve email account: %s", err.message);
+ }
+ }
+
+ return false;
+ }
+
private void open_account(string email, string? old_imap_password, string? old_smtp_password,
PasswordTypeFlag password_flags, Cancellable? cancellable) {
Geary.AccountInformation account_information;
@@ -368,17 +384,25 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
// Prompt the user for a service, real name, username, and password, and try to start Geary.
private Geary.AccountInformation? request_account_information(Geary.AccountInformation? old_info) {
Geary.AccountInformation? new_info = old_info;
+ if (login_dialog == null)
+ login_dialog = new LoginDialog(); // Create here so we know GTK is initialized.
+
+ if (new_info == null)
+ login_dialog.set_real_name(get_default_real_name());
+ else
+ login_dialog.set_account_information(new_info);
+
+ login_dialog.present();
for (;;) {
- LoginDialog login_dialog = (new_info == null) ? new LoginDialog(get_default_real_name())
- : new LoginDialog.from_account_information(new_info);
-
- if (!login_dialog.show()) {
+ login_dialog.show_spinner(false);
+ if (login_dialog.run() != Gtk.ResponseType.OK) {
debug("User refused to enter account information. Exiting...");
exit(1);
return null;
}
- new_info = login_dialog.account_information;
+ login_dialog.show_spinner(true);
+ new_info = login_dialog.get_account_information();
if ((!new_info.default_imap_server_ssl && !new_info.default_imap_server_starttls)
|| (!new_info.default_smtp_server_ssl && !new_info.default_smtp_server_starttls)) {
@@ -392,7 +416,7 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
break;
}
-
+
if (new_info.imap_remember_password)
keyring_save_password(new_info.imap_credentials, PasswordType.IMAP);
else
diff --git a/src/client/geary-controller.vala b/src/client/geary-controller.vala
index 9e50de0d..2e9dae3b 100644
--- a/src/client/geary-controller.vala
+++ b/src/client/geary-controller.vala
@@ -18,6 +18,7 @@ public class GearyController {
public const string ACTION_ZOOM_IN = "GearyZoomIn";
public const string ACTION_ZOOM_OUT = "GearyZoomOut";
public const string ACTION_ZOOM_NORMAL = "GearyZoomNormal";
+ public const string ACTION_ACCOUNTS = "GearyAccounts";
public const string ACTION_PREFERENCES = "GearyPreferences";
public const string ACTION_MARK_AS_MENU = "GearyMarkAsMenuButton";
public const string ACTION_MARK_AS_READ = "GearyMarkAsRead";
@@ -130,6 +131,11 @@ public class GearyController {
private Gtk.ActionEntry[] create_actions() {
Gtk.ActionEntry[] entries = new Gtk.ActionEntry[0];
+ Gtk.ActionEntry accounts = { ACTION_ACCOUNTS, null, TRANSLATABLE, null,
+ null, on_accounts };
+ accounts.label = _("A_ccounts");
+ entries += accounts;
+
Gtk.ActionEntry prefs = { ACTION_PREFERENCES, Gtk.Stock.PREFERENCES, TRANSLATABLE, null,
null, on_preferences };
prefs.label = _("_Preferences");
@@ -700,6 +706,12 @@ public class GearyController {
clear_new_messages("on_has_toplevel_focus", null);
}
+ private void on_accounts() {
+ AccountDialog dialog = new AccountDialog();
+ dialog.run();
+ dialog.destroy();
+ }
+
private void on_preferences() {
PreferencesDialog dialog = new PreferencesDialog(GearyApplication.instance.config);
dialog.run();
diff --git a/ui/account_list.glade b/ui/account_list.glade
new file mode 100644
index 00000000..ef6d6fcf
--- /dev/null
+++ b/ui/account_list.glade
@@ -0,0 +1,109 @@
+
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ True
+ True
+ True
+ in
+
+
+ True
+ True
+ True
+ True
+ False
+ False
+ False
+ False
+
+
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ False
+ icons
+ False
+ 2
+
+
+
+ add_account
+ True
+ False
+ Add an account
+ toolbutton1
+ True
+
+
+ False
+ True
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ 5
+ 5
+ end
+
+
+ close
+ True
+ False
+ False
+ True
+ 0.54000002145767212
+
+
+ False
+ True
+ 0
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
diff --git a/ui/account_spinner.glade b/ui/account_spinner.glade
new file mode 100644
index 00000000..1764f680
--- /dev/null
+++ b/ui/account_spinner.glade
@@ -0,0 +1,64 @@
+
+
+
+
+ True
+ False
+ vertical
+ 15
+
+
+ True
+ False
+
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ 45
+ 45
+ True
+ False
+ True
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ Please wait while Geary validates your account.
+
+
+ False
+ True
+ 2
+
+
+
+
+ True
+ False
+
+
+
+
+
+ True
+ True
+ 3
+
+
+
+
diff --git a/ui/login.glade b/ui/login.glade
index 90dd5686..156f45ee 100644
--- a/ui/login.glade
+++ b/ui/login.glade
@@ -1,132 +1,469 @@
-
- 450
+
+ True
False
- True
- 5
- dialog
-
-
+ vertical
+ 2
+
+
True
False
- vertical
- 2
-
+
True
False
-
-
- True
- False
- 64
- geary
-
-
- False
- True
- 8
- 0
-
-
-
-
- True
- False
- start
- True
- True
-
-
- True
- True
- 1
-
-
+ 64
+ geary
False
True
- 12
+ 8
0
-
-
+
+
True
False
- end
-
-
-
-
-
-
+ start
+ True
+ True
- False
- False
- 6
- end
+ True
+ True
1
+
+
+ False
+ True
+ 12
+ 0
+
+
+
+
+ True
+ False
+ 2
+ 4
-
+
+ True
+ True
+ True
+ •
+ True
+ 0
+ True
+ False
+ False
+ email@example.com
+
+
+ 1
+ 2
+ 1
+ 1
+
+
+
+
+ True
+ True
+ True
+ False
+ •
+ True
+ True
+ False
+ False
+ Password
+
+
+ 1
+ 3
+ 1
+ 1
+
+
+
+
+ True
+ False
+ 0
+ _Email address:
+ True
+ entry: email
+
+
+ 0
+ 2
+ 1
+ 1
+
+
+
+
+ True
+ False
+ 0
+ _Password:
+ True
+ entry: password
+
+
+ 0
+ 3
+ 1
+ 1
+
+
+
+
+ True
+ False
+ True
+
+
+ 1
+ 0
+ 1
+ 1
+
+
+
+
+ True
+ False
+ 0
+ _Service:
+ True
+ combo: service
+
+
+ 0
+ 0
+ 1
+ 1
+
+
+
+
+ True
+ False
+ 0
+ N_ame:
+ True
+ entry: real_name
+
+
+ 0
+ 1
+ 1
+ 1
+
+
+
+
+ True
+ True
+ True
+ •
+ True
+ True
+ False
+ False
+ First Last
+
+
+ 1
+ 1
+ 1
+ 1
+
+
+
+
+ Re_member password
+ True
+ True
+ False
+ True
+ 0
+ True
+ True
+
+
+ 1
+ 4
+ 1
+ 1
+
+
+
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ False
+
+
True
False
2
4
-
+
True
- True
- True
- •
- True
- 0
- True
- False
- False
- email@example.com
+ False
+ 0
+ 10
+ IMAP settings
+
+
+
- 1
- 2
+ 0
+ 0
+ 4
+ 1
+
+
+
+
+ True
+ False
+ 0
+ 12
+ Se_rver:
+ True
+ entry: imap host
+
+
+ 0
+ 1
1
1
-
+
True
True
True
+ •
+ imap.example.com
+
+
+ 1
+ 1
+ 1
+ 1
+
+
+
+
+ True
+ False
+ 0
+ 12
+ P_ort:
+ True
+ entry: imap port
+
+
+ 2
+ 1
+ 1
+ 1
+
+
+
+
+ True
+ True
+ •
+ 5
+ 993
+ True
+
+
+ 3
+ 1
+ 1
+ 1
+
+
+
+
+ True
+ True
+ •
+ True
+ smtp.example.com
+
+
+ 1
+ 9
+ 1
+ 1
+
+
+
+
+ True
+ True
+ •
+ 5
+ 465
+ True
+
+
+ 3
+ 9
+ 1
+ 1
+
+
+
+
+ True
+ False
+ 0
+ 12
+ Ser_ver:
+ True
+ entry: smtp host
+
+
+ 0
+ 9
+ 1
+ 1
+
+
+
+
+ True
+ False
+ 0
+ 12
+ Por_t:
+ True
+ entry: smtp port
+
+
+ 2
+ 9
+ 1
+ 1
+
+
+
+
+ True
+ False
+ 8
+ 0
+ 10
+ SMTP settings
+
+
+
+
+
+ 0
+ 8
+ 1
+ 1
+
+
+
+
+ True
+ False
+ 0
+ 12
+ User_name:
+ True
+ entry: smtp username
+
+
+ 0
+ 10
+ 1
+ 1
+
+
+
+
+ True
+ False
+ 0
+ 12
+ Pass_word:
+ True
+ entry: smtp password
+
+
+ 0
+ 11
+ 1
+ 1
+
+
+
+
+ True
+ True
+ •
+ SMTP username
+
+
+ 1
+ 10
+ 3
+ 1
+
+
+
+
+ True
+ True
False
•
- True
- True
- False
- False
- Password
+ SMTP password
1
- 3
- 1
+ 11
+ 3
1
-
+
True
False
0
- _Email address:
+ 12
+ _Username:
True
- entry: email
+ entry: imap username
0
@@ -136,13 +473,14 @@
-
+
True
False
0
+ 12
_Password:
True
- entry: password
+ entry: imap password
0
@@ -152,546 +490,177 @@
-
- True
- False
- True
-
-
- 1
- 0
- 1
- 1
-
-
-
-
- True
- False
- 0
- _Service:
- True
- combo: service
-
-
- 0
- 0
- 1
- 1
-
-
-
-
- True
- False
- 0
- N_ame:
- True
- entry: real_name
-
-
- 0
- 1
- 1
- 1
-
-
-
-
+
True
True
- True
•
- True
- True
- False
- False
- First Last
+ IMAP username
1
- 1
+ 2
+ 3
+ 1
+
+
+
+
+ True
+ True
+ False
+ •
+ IMAP password
+
+
+ 1
+ 3
+ 3
+ 1
+
+
+
+
+ True
+ False
+ 2
+ 0
+ 12
+ Encr_yption:
+ True
+ center
+ combo: imap encryption
+
+
+ 0
+ 5
1
1
-
- Re_member password
- False
+
True
- True
- False
- False
- True
+ False
+ 2
0
- True
- True
+ 12
+ Encrypt_ion:
+ True
+ fill
+ combo: smtp encryption
+
+
+ 0
+ 13
+ 1
+ 1
+
+
+
+
+ True
+ False
+ 1
+ 0
+ 1
+
+ - None
+ - SSL/TLS
+ - STARTTLS
+
1
- 4
- 1
+ 5
+ 3
+ 1
+
+
+
+
+ True
+ False
+ 1
+ 0
+ 1
+
+ - None
+ - SSL/TLS
+ - STARTTLS
+
+
+
+ 1
+ 13
+ 3
1
-
-
- False
- True
- 2
-
-
-
-
- False
-
- True
- False
- 2
- 4
-
-
- True
- False
- 0
- 10
- IMAP settings
-
-
-
-
-
- 0
- 0
- 4
- 1
-
-
-
-
- True
- False
- 0
- 12
- Se_rver:
- True
- entry: imap host
-
-
- 0
- 1
- 1
- 1
-
-
-
-
- True
- True
- True
- •
- imap.example.com
-
-
- 1
- 1
- 1
- 1
-
-
-
-
- True
- False
- 0
- 12
- P_ort:
- True
- entry: imap port
-
-
- 2
- 1
- 1
- 1
-
-
-
-
- True
- True
- •
- 5
- 993
- True
-
-
- 3
- 1
- 1
- 1
-
-
-
-
- True
- True
- •
- True
- smtp.example.com
-
-
- 1
- 9
- 1
- 1
-
-
-
-
- True
- True
- •
- 5
- 465
- True
-
-
- 3
- 9
- 1
- 1
-
-
-
-
- True
- False
- 0
- 12
- Ser_ver:
- True
- entry: smtp host
-
-
- 0
- 9
- 1
- 1
-
-
-
-
- True
- False
- 0
- 12
- Por_t:
- True
- entry: smtp port
-
-
- 2
- 9
- 1
- 1
-
-
-
-
- True
- False
- 8
- 0
- 10
- SMTP settings
-
-
-
-
-
- 0
- 8
- 1
- 1
-
-
-
-
- True
- False
- 0
- 12
- User_name:
- True
- entry: smtp username
-
-
- 0
- 10
- 1
- 1
-
-
-
-
- True
- False
- 0
- 12
- Pass_word:
- True
- entry: smtp password
-
-
- 0
- 11
- 1
- 1
-
-
-
-
- True
- True
- •
- SMTP username
-
-
- 1
- 10
- 3
- 1
-
-
-
-
- True
- True
- False
- •
- SMTP password
-
-
- 1
- 11
- 3
- 1
-
-
-
-
- True
- False
- 0
- 12
- _Username:
- True
- entry: imap username
-
-
- 0
- 2
- 1
- 1
-
-
-
-
- True
- False
- 0
- 12
- _Password:
- True
- entry: imap password
-
-
- 0
- 3
- 1
- 1
-
-
-
-
- True
- True
- •
- IMAP username
-
-
- 1
- 2
- 3
- 1
-
-
-
-
- True
- True
- False
- •
- IMAP password
-
-
- 1
- 3
- 3
- 1
-
-
-
-
- True
- False
- 2
- 0
- 12
- Encr_yption:
- True
- center
- combo: imap encryption
-
-
- 0
- 5
- 1
- 1
-
-
-
-
- True
- False
- 2
- 0
- 12
- Encrypt_ion:
- True
- fill
- combo: smtp encryption
-
-
- 0
- 13
- 1
- 1
-
-
-
-
- True
- False
- 1
- 0
- 1
-
- - None
- - SSL/TLS
- - STARTTLS
-
-
-
- 1
- 5
- 3
- 1
-
-
-
-
- True
- False
- 1
- 0
- 1
-
- - None
- - SSL/TLS
- - STARTTLS
-
-
-
- 1
- 13
- 3
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
- False
- True
- 3
-
+
+ False
+ True
+ 3
+
diff --git a/ui/toolbar_menu.ui b/ui/toolbar_menu.ui
index 17c5b3f3..cdc86a9e 100644
--- a/ui/toolbar_menu.ui
+++ b/ui/toolbar_menu.ui
@@ -3,6 +3,7 @@
If ToolbarMenu is changed, be sure to update ToolbarMenuProxy as well. See comments below.
-->
+
@@ -17,6 +18,7 @@
we keep a duplicate of ToolbarMenu in this .ui file to be used by the proxy.
-->
+