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 @@ + + + + + + + list-add-symbolic + + + + + gtk-close + + + + + 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. --> +