[geary/wip/714922-multiple-addresses-2: 5/5] First work on UI for adding/removing add'tl email addresses
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/714922-multiple-addresses-2: 5/5] First work on UI for adding/removing add'tl email addresses
- Date: Tue, 10 Feb 2015 22:08:21 +0000 (UTC)
commit 025403f0d50cb782f34d0c9c2e0445214026cd15
Author: Jim Nelson <jim yorba org>
Date: Tue Feb 10 14:07:28 2015 -0800
First work on UI for adding/removing add'tl email addresses
po/POTFILES.in | 2 +
src/CMakeLists.txt | 1 +
.../accounts/account-dialog-add-edit-pane.vala | 5 +-
.../account-dialog-edit-alternate-emails-pane.vala | 113 ++++++++++++
src/client/accounts/account-dialog.vala | 17 ++
src/client/accounts/add-edit-page.vala | 11 ++
src/engine/api/geary-account-information.vala | 10 +
ui/CMakeLists.txt | 1 +
ui/edit_alternate_emails.glade | 188 ++++++++++++++++++++
ui/login.glade | 13 ++-
10 files changed, 359 insertions(+), 2 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index e8e88cb..2b953c9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -4,6 +4,7 @@ desktop/geary-autostart.desktop.in
[type: gettext/ini]desktop/geary-attach.contract.in
src/client/accounts/account-dialog-account-list-pane.vala
src/client/accounts/account-dialog-add-edit-pane.vala
+src/client/accounts/account-dialog-edit-alternate-emails-pane.vala
src/client/accounts/account-dialog-pane.vala
src/client/accounts/account-dialog-remove-confirm-pane.vala
src/client/accounts/account-dialog-remove-fail-pane.vala
@@ -371,6 +372,7 @@ src/mailer/main.vala
[type: gettext/glade]ui/certificate_warning_dialog.glade
[type: gettext/glade]ui/composer_accelerators.ui
[type: gettext/glade]ui/composer.glade
+[type: gettext/glade]ui/edit_alternate_emails.glade
[type: gettext/glade]ui/find_bar.glade
[type: gettext/glade]ui/login.glade
[type: gettext/glade]ui/message.glade
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6ee272d..5c9cd27 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -317,6 +317,7 @@ client/application/secret-mediator.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-dialog-edit-alternate-emails-pane.vala
client/accounts/account-dialog-pane.vala
client/accounts/account-dialog-remove-confirm-pane.vala
client/accounts/account-dialog-remove-fail-pane.vala
diff --git a/src/client/accounts/account-dialog-add-edit-pane.vala
b/src/client/accounts/account-dialog-add-edit-pane.vala
index 398c9eb..65d30ed 100644
--- a/src/client/accounts/account-dialog-add-edit-pane.vala
+++ b/src/client/accounts/account-dialog-add-edit-pane.vala
@@ -17,6 +17,8 @@ public class AccountDialogAddEditPane : AccountDialogPane {
public signal void size_changed();
+ public signal void edit_alternate_emails(string email_address);
+
public AccountDialogAddEditPane(Gtk.Stack stack) {
base(stack);
@@ -35,7 +37,8 @@ public class AccountDialogAddEditPane : AccountDialogPane {
ok_button.clicked.connect(on_ok);
cancel_button.clicked.connect(() => { cancel(); });
- add_edit_page.size_changed.connect(() => { size_changed(); } );
+ add_edit_page.size_changed.connect(() => { size_changed(); });
+ add_edit_page.edit_alternate_emails.connect(() => {
edit_alternate_emails(add_edit_page.email_address); });
pack_start(add_edit_page);
pack_start(button_box, false, false);
diff --git a/src/client/accounts/account-dialog-edit-alternate-emails-pane.vala
b/src/client/accounts/account-dialog-edit-alternate-emails-pane.vala
new file mode 100644
index 0000000..64bb559
--- /dev/null
+++ b/src/client/accounts/account-dialog-edit-alternate-emails-pane.vala
@@ -0,0 +1,113 @@
+/* Copyright 2015 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 AccountDialogEditAlternateEmailsPane : AccountDialogPane {
+ private class ListItem : Gtk.Label {
+ public Geary.RFC822.MailboxAddress mailbox;
+
+ public ListItem(Geary.RFC822.MailboxAddress mailbox) {
+ this.mailbox = mailbox;
+
+ label = "<b>%s</b>".printf(mailbox.address);
+ use_markup = true;
+ ellipsize = Pango.EllipsizeMode.END;
+ }
+ }
+
+ public string? email { get; private set; default = null; }
+
+ public bool changed { get; private set; default = false; }
+
+ public string? selected { get; private set; default = null; }
+
+ private Gtk.Label title_label;
+ private Gtk.Entry email_entry;
+ private Gtk.Button add_button;
+ private Gtk.ListBox address_listbox;
+ private Gtk.ToolButton delete_button;
+ private Gtk.Button cancel_button;
+ private Gtk.Button save_button;
+
+ private Geary.RFC822.MailboxAddress? primary_mailbox = null;
+ private Gee.HashSet<string> email_addresses = new Gee.HashSet<string>(
+ Geary.String.stri_hash, Geary.String.stri_equal);
+
+ public signal void cancelled();
+
+ public AccountDialogEditAlternateEmailsPane(Gtk.Stack stack) {
+ base (stack);
+
+ Gtk.Builder builder = GearyApplication.instance.create_builder("edit_alternate_emails.glade");
+
+ // Primary container
+ pack_start((Gtk.Widget) builder.get_object("container"));
+
+ title_label = (Gtk.Label) builder.get_object("title_label");
+ email_entry = (Gtk.Entry) builder.get_object("email_entry");
+ add_button = (Gtk.Button) builder.get_object("add_button");
+ address_listbox = (Gtk.ListBox) builder.get_object("address_listbox");
+ delete_button = (Gtk.ToolButton) builder.get_object("delete_button");
+ cancel_button = (Gtk.Button) builder.get_object("cancel_button");
+ save_button = (Gtk.Button) builder.get_object("save_button");
+
+ email_entry.bind_property("text", add_button, "sensitive", BindingFlags.SYNC_CREATE,
+ transform_email_to_sensitive);
+ bind_property("changed", save_button, "sensitive", BindingFlags.SYNC_CREATE);
+ bind_property("selected", delete_button, "sensitive", BindingFlags.SYNC_CREATE);
+
+ cancel_button.clicked.connect(() => { cancelled(); });
+ add_button.clicked.connect(on_add_clicked);
+ }
+
+ private bool transform_email_to_sensitive(Binding binding, Value source, ref Value target) {
+ target = Geary.RFC822.MailboxAddress.is_valid_address(email_entry.text);
+
+ return true;
+ }
+
+ public void set_account(Geary.AccountInformation account_info) {
+ email = account_info.email;
+ primary_mailbox = account_info.get_primary_mailbox_address();
+ changed = false;
+
+ // reset/clear widgets
+ title_label.label = _("Additional addresses for %s").printf(account_info.email);
+ email_entry.text = "";
+
+ // clear listbox
+ foreach (Gtk.Widget widget in address_listbox.get_children())
+ address_listbox.remove(widget);
+
+ // Add all except for primary; this does not constitute a change per se
+ foreach (string email_address in account_info.get_all_email_addresses())
+ add_email_address(email_address, false);
+ }
+
+ private void add_email_address(string email_address, bool is_change) {
+ if (email_addresses.contains(email_address))
+ return;
+
+ if (!Geary.RFC822.MailboxAddress.is_valid_address(email_address))
+ return;
+
+ if (Geary.String.stri_equal(email_address, primary_mailbox.address))
+ return;
+
+ email_addresses.add(email_address);
+
+ ListItem item = new ListItem(new Geary.RFC822.MailboxAddress(null, email_address));
+ item.show_all();
+ address_listbox.add(item);
+
+ if (is_change)
+ changed = true;
+ }
+
+ private void on_add_clicked() {
+ add_email_address(email_entry.text, true);
+ }
+}
+
diff --git a/src/client/accounts/account-dialog.vala b/src/client/accounts/account-dialog.vala
index 1d42763..1e48847 100644
--- a/src/client/accounts/account-dialog.vala
+++ b/src/client/accounts/account-dialog.vala
@@ -13,6 +13,7 @@ public class AccountDialog : Gtk.Dialog {
private AccountDialogSpinnerPane spinner_pane;
private AccountDialogRemoveConfirmPane remove_confirm_pane;
private AccountDialogRemoveFailPane remove_fail_pane;
+ private AccountDialogEditAlternateEmailsPane edit_alternate_emails_pane;
private Gtk.HeaderBar headerbar = new Gtk.HeaderBar();
public AccountDialog(Gtk.Window parent) {
@@ -33,6 +34,7 @@ public class AccountDialog : Gtk.Dialog {
spinner_pane = new AccountDialogSpinnerPane(stack);
remove_confirm_pane = new AccountDialogRemoveConfirmPane(stack);
remove_fail_pane = new AccountDialogRemoveFailPane(stack);
+ edit_alternate_emails_pane = new AccountDialogEditAlternateEmailsPane(stack);
// Connect signals from pages.
account_list_pane.add_account.connect(on_add_account);
@@ -41,9 +43,11 @@ public class AccountDialog : Gtk.Dialog {
add_edit_pane.ok.connect(on_save_add_or_edit);
add_edit_pane.cancel.connect(on_cancel_back_to_list);
add_edit_pane.size_changed.connect(() => { resize(1, 1); });
+ add_edit_pane.edit_alternate_emails.connect(on_edit_alternate_emails);
remove_confirm_pane.ok.connect(on_delete_account_confirmed);
remove_confirm_pane.cancel.connect(on_cancel_back_to_list);
remove_fail_pane.ok.connect(on_cancel_back_to_list);
+ edit_alternate_emails_pane.cancelled.connect(on_cancel_back_to_editor);
// Set default page.
account_list_pane.present();
@@ -132,6 +136,15 @@ public class AccountDialog : Gtk.Dialog {
}
}
+ private void on_edit_alternate_emails(string email_address) {
+ Geary.AccountInformation? account_info = get_account_info_for_email(email_address);
+ if (account_info == null)
+ return;
+
+ edit_alternate_emails_pane.set_account(account_info);
+ edit_alternate_emails_pane.present();
+ }
+
private void on_delete_account_confirmed(Geary.AccountInformation? account) {
assert(account != null); // Should not be able to happen since we checked earlier.
@@ -197,5 +210,9 @@ public class AccountDialog : Gtk.Dialog {
private void on_cancel_back_to_list() {
account_list_pane.present();
}
+
+ private void on_cancel_back_to_editor() {
+ add_edit_pane.present();
+ }
}
diff --git a/src/client/accounts/add-edit-page.vala b/src/client/accounts/add-edit-page.vala
index 80ec59e..226a990 100644
--- a/src/client/accounts/add-edit-page.vala
+++ b/src/client/accounts/add-edit-page.vala
@@ -169,6 +169,7 @@ public class AddEditPage : Gtk.Box {
private Gtk.ComboBoxText combo_service;
private Gtk.CheckButton check_remember_password;
private Gtk.CheckButton check_save_sent_mail;
+ private Gtk.Button alternate_email_button;
// Signature
private Gtk.Box composer_container;
@@ -215,6 +216,8 @@ public class AddEditPage : Gtk.Box {
public signal void size_changed();
+ public signal void edit_alternate_emails();
+
public AddEditPage() {
Object(orientation: Gtk.Orientation.VERTICAL, spacing: 4);
@@ -239,6 +242,7 @@ public class AddEditPage : Gtk.Box {
entry_password = (Gtk.Entry) builder.get_object("entry: password");
check_remember_password = (Gtk.CheckButton) builder.get_object("check: remember_password");
check_save_sent_mail = (Gtk.CheckButton) builder.get_object("check: save_sent_mail");
+ alternate_email_button = (Gtk.Button) builder.get_object("button: edit_alternate_email");
label_error = (Gtk.Label) builder.get_object("label: error");
other_info = (Gtk.Alignment) builder.get_object("container: other_info");
@@ -328,6 +332,7 @@ public class AddEditPage : Gtk.Box {
check_smtp_use_imap_credentials.toggled.connect(on_changed);
check_smtp_noauth.toggled.connect(on_changed);
check_save_drafts.toggled.connect(on_changed);
+ alternate_email_button.clicked.connect(on_alternate_email_button_clicked);
entry_email.changed.connect(on_email_changed);
entry_password.changed.connect(on_password_changed);
@@ -496,6 +501,10 @@ public class AddEditPage : Gtk.Box {
info_changed();
}
+ private void on_alternate_email_button_clicked() {
+ edit_alternate_emails();
+ }
+
// Prevent non-printable characters in nickname field.
private void on_nickname_insert_text(Gtk.Editable e, string text, int length, ref int position) {
unichar c;
@@ -696,12 +705,14 @@ public class AddEditPage : Gtk.Box {
// Updates UI based on various options.
internal void update_ui() {
base.show_all();
+
welcome_box.visible = mode == PageMode.WELCOME;
entry_nickname.visible = label_nickname.visible = mode != PageMode.WELCOME;
storage_container.visible = mode == PageMode.EDIT;
check_save_sent_mail.visible = mode == PageMode.EDIT;
check_save_drafts.visible = mode == PageMode.EDIT;
composer_container.visible = mode == PageMode.EDIT;
+ alternate_email_button.visible = mode == PageMode.EDIT;
if (get_service_provider() == Geary.ServiceProvider.OTHER) {
// Display all options for custom providers.
diff --git a/src/engine/api/geary-account-information.vala b/src/engine/api/geary-account-information.vala
index e87edfb..1dde784 100644
--- a/src/engine/api/geary-account-information.vala
+++ b/src/engine/api/geary-account-information.vala
@@ -60,7 +60,17 @@ public class Geary.AccountInformation : BaseObject {
public string real_name { get; set; }
public string nickname { get; set; }
+ /**
+ * The primary email address for the account.
+ *
+ * @see get_all_email_addresses
+ */
public string email { get; set; }
+ /**
+ * A list of additional email addresses this account accepts.
+ *
+ * @see get_all_email_addresses
+ */
public Gee.List<string>? alternate_emails { get; set; }
public Geary.ServiceProvider service_provider { get; set; }
public int prefetch_period_days { get; set; }
diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt
index bb1329f..c403483 100644
--- a/ui/CMakeLists.txt
+++ b/ui/CMakeLists.txt
@@ -8,6 +8,7 @@ install(FILES app_menu.interface DESTINATION ${UI_DEST})
install(FILES certificate_warning_dialog.glade DESTINATION ${UI_DEST})
install(FILES composer.glade DESTINATION ${UI_DEST})
install(FILES composer_accelerators.ui DESTINATION ${UI_DEST})
+install(FILES edit_alternate_emails.glade DESTINATION ${UI_DEST})
install(FILES find_bar.glade DESTINATION ${UI_DEST})
install(FILES login.glade DESTINATION ${UI_DEST})
install(FILES message.glade DESTINATION ${UI_DEST})
diff --git a/ui/edit_alternate_emails.glade b/ui/edit_alternate_emails.glade
new file mode 100644
index 0000000..9a43861
--- /dev/null
+++ b/ui/edit_alternate_emails.glade
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.16.1 -->
+<interface>
+ <requires lib="gtk+" version="3.10"/>
+ <object class="GtkBox" id="container">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkLabel" id="title_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_bottom">8</property>
+ <property name="label">(added in code)</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkEntry" id="email_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="input_purpose">email</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="add_button">
+ <property name="label" translatable="yes">_Add</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport" id="viewport1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkListBox" id="address_listbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="activate_on_single_click">False</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolbar" id="toolbar1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="toolbar_style">icons</property>
+ <property name="show_arrow">False</property>
+ <property name="icon_size">2</property>
+ <child>
+ <object class="GtkToolButton" id="delete_button">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Remove email address</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">list-remove-symbolic</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <style>
+ <class name="inline-toolbar"/>
+ </style>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Some email services require additional addresses be
configured on the server. Contact your email provider for more information.</property>
+ <property name="wrap">True</property>
+ <attributes>
+ <attribute name="style" value="italic"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox" id="buttonbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">end</property>
+ <property name="margin_top">8</property>
+ <property name="vexpand">False</property>
+ <property name="spacing">8</property>
+ <property name="homogeneous">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="cancel_button">
+ <property name="label" translatable="yes">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="save_button">
+ <property name="label" translatable="yes">_Save</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/ui/login.glade b/ui/login.glade
index 1e85ad0..8eb92e3 100644
--- a/ui/login.glade
+++ b/ui/login.glade
@@ -298,7 +298,18 @@
</packing>
</child>
<child>
- <placeholder/>
+ <object class="GtkButton" id="button: edit_alternate_email">
+ <property name="label" translatable="yes">Add_itional email addresses…</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">7</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
</child>
<child>
<placeholder/>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]