diff --git a/po/POTFILES.in b/po/POTFILES.in index 4cd98244..35b8c704 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -18,6 +18,8 @@ src/client/accounts/account-dialogs.vala src/client/accounts/account-manager.vala src/client/accounts/account-spinner-page.vala src/client/accounts/accounts-editor.vala +src/client/accounts/accounts-editor-edit-pane.vala +src/client/accounts/accounts-editor-row.vala src/client/accounts/add-edit-page.vala src/client/accounts/editor.vala src/client/accounts/goa-service-information.vala @@ -408,6 +410,7 @@ ui/account_cannot_remove.glade ui/account_list.glade ui/account_spinner.glade ui/accounts_editor.ui +ui/accounts_editor_edit_pane.ui ui/certificate_warning_dialog.glade ui/composer-headerbar.ui ui/composer-link-popover.ui diff --git a/src/client/accounts/accounts-editor-edit-pane.vala b/src/client/accounts/accounts-editor-edit-pane.vala new file mode 100644 index 00000000..932efd1b --- /dev/null +++ b/src/client/accounts/accounts-editor-edit-pane.vala @@ -0,0 +1,161 @@ +/* + * Copyright 2018 Michael Gratton + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +/** + * The main account editor window. + */ +[GtkTemplate (ui = "/org/gnome/Geary/accounts_editor_edit_pane.ui")] +public class Accounts.EditorEditPane : Gtk.Grid { + + + private Geary.AccountInformation account; + + [GtkChild] + private Gtk.ListBox details_list; + + [GtkChild] + private Gtk.ListBox addresses_list; + + [GtkChild] + private Gtk.ScrolledWindow signature_scrolled; + + private ClientWebView signature_preview; + + [GtkChild] + private Gtk.ListBox settings_list; + + + public EditorEditPane(GearyApplication application, + Geary.AccountInformation account) { + this.account = account; + + PropertyRow nickname_row = new PropertyRow( + account, + "nickname", + // Translators: This label in the account editor is for + // the user's name for an account. + _("Account name") + ); + nickname_row.set_dim_label(true); + + this.details_list.set_header_func(Editor.seperator_headers); + this.details_list.add(nickname_row); + + this.addresses_list.set_header_func(Editor.seperator_headers); + this.addresses_list.add( + new AddressRow(account.primary_mailbox, get_login_session_name()) + ); + + string? default_name = account.primary_mailbox.name; + if (Geary.String.is_empty_or_whitespace(default_name)) { + default_name = null; + } + if (account.alternate_mailboxes != null) { + foreach (Geary.RFC822.MailboxAddress alt + in account.alternate_mailboxes) { + this.addresses_list.add(new AddressRow(alt, default_name)); + } + } + + this.addresses_list.add(new AddRow()); + + this.signature_preview = new ClientWebView(application.config); + this.signature_preview.load_html(account.email_signature); + this.signature_preview.show(); + + this.signature_scrolled.add(this.signature_preview); + + this.settings_list.set_header_func(Editor.seperator_headers); + // No settings to show at the moment, so hide the list and its + // frame until we do. + this.settings_list.get_parent().hide(); + } + + private string? get_login_session_name() { + string? name = Environment.get_real_name(); + if (Geary.String.is_empty(name) || name == "Unknown") { + name = null; + } + return name; + } + +} + + +private class Accounts.PropertyRow : LabelledEditorRow { + + + private GLib.Object object; + private string property_name; + + private Gtk.Label value = new Gtk.Label(""); + + + public PropertyRow(Object object, + string property_name, + string label) { + base(label); + + this.object = object; + this.property_name = property_name; + + this.value.show(); + this.layout.add(this.value); + + update(); + } + + public void update() { + string? value = null; + this.object.get(this.property_name, ref value); + + if (value != null) { + this.value.set_text(value); + } + } + +} + + +private class Accounts.AddressRow : LabelledEditorRow { + + + private Geary.RFC822.MailboxAddress address; + private string? fallback_name; + + private Gtk.Label value = new Gtk.Label(""); + + + public AddressRow(Geary.RFC822.MailboxAddress address, + string? fallback_name) { + base(""); + this.address = address; + this.fallback_name = fallback_name; + + this.value.show(); + this.layout.add(this.value); + + update(); + } + + public void update() { + string? name = Geary.String.is_empty_or_whitespace(this.address.name) + ? this.fallback_name + : this.address.name; + + if (Geary.String.is_empty_or_whitespace(name)) { + name = _("No name set"); + set_dim_label(true); + } else { + set_dim_label(false); + } + + this.label.set_text(name); + this.value.set_text(this.address.address.strip()); + } + +} diff --git a/src/client/accounts/accounts-editor-row.vala b/src/client/accounts/accounts-editor-row.vala new file mode 100644 index 00000000..f142897b --- /dev/null +++ b/src/client/accounts/accounts-editor-row.vala @@ -0,0 +1,68 @@ +/* + * Copyright 2018 Michael Gratton + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + + +internal class Accounts.EditorRow : Gtk.ListBoxRow { + + + protected Gtk.Grid layout { get; private set; default = new Gtk.Grid(); } + + + public EditorRow() { + get_style_context().add_class("geary-settings"); + + this.layout.orientation = Gtk.Orientation.HORIZONTAL; + this.layout.show(); + add(this.layout); + + this.show(); + } + +} + + +internal class Accounts.LabelledEditorRow : EditorRow { + + + protected Gtk.Label label { get; private set; default = new Gtk.Label(""); } + + + public LabelledEditorRow(string label) { + this.label.set_text(label); + this.label.set_hexpand(true); + this.label.halign = Gtk.Align.START; + this.label.show(); + + this.layout.add(this.label); + } + + public void set_dim_label(bool is_dim) { + if (is_dim) { + this.label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL); + } else { + this.label.get_style_context().remove_class(Gtk.STYLE_CLASS_DIM_LABEL); + } + } + +} + + +internal class Accounts.AddRow : EditorRow { + + + public AddRow() { + Gtk.Image add_icon = new Gtk.Image.from_icon_name( + "list-add-symbolic", Gtk.IconSize.BUTTON + ); + add_icon.set_hexpand(true); + add_icon.show(); + + this.layout.add(add_icon); + } + + +} diff --git a/src/client/accounts/accounts-editor.vala b/src/client/accounts/accounts-editor.vala index eb4729ab..cdf46c4e 100644 --- a/src/client/accounts/accounts-editor.vala +++ b/src/client/accounts/accounts-editor.vala @@ -12,6 +12,15 @@ public class Accounts.Editor : Gtk.Dialog { + internal static void seperator_headers(Gtk.ListBoxRow row, + Gtk.ListBoxRow? first) { + if (first == null) { + row.set_header(null); + } else if (row.get_header() == null) { + row.set_header(new Gtk.Separator(Gtk.Orientation.HORIZONTAL)); + } + } + private static int ordinal_sort(Gtk.ListBoxRow a, Gtk.ListBoxRow b) { AccountRow? account_a = a as AccountRow; AccountRow? account_b = b as AccountRow; @@ -27,25 +36,46 @@ public class Accounts.Editor : Gtk.Dialog { ); } - private static void update_header(Gtk.ListBoxRow row, Gtk.ListBoxRow? first) { - if (first == null) { - row.set_header(null); - } else if (row.get_header() == null) { - row.set_header(new Gtk.Separator(Gtk.Orientation.HORIZONTAL)); - } - } + + /** + * The current application instance. + * + * Note this hides the {@link GtkWindow.application} property + * since we don't want the application to know about this dialog - + * it should not prevent the app from closing. + */ + internal new GearyApplication application { get; private set; } private AccountManager accounts; + [GtkChild] + private Gtk.HeaderBar default_header; + + [GtkChild] + private Gtk.Stack editor_panes; + + [GtkChild] + private Gtk.Button back_button; + + [GtkChild] + private Gtk.Grid list_pane; + [GtkChild] private Gtk.ListBox accounts_list; - public Editor(AccountManager accounts, Gtk.Window parent) { - this.accounts = accounts; - set_transient_for(parent); + public Editor(GearyApplication application, Gtk.Window parent) { + this.application = application; + this.accounts = application.controller.account_manager; - this.accounts_list.set_header_func(update_header); + set_titlebar(this.default_header); + set_transient_for(parent); + set_modal(true); + + // XXX Glade 3.22 won't let us set this + get_content_area().border_width = 2; + + this.accounts_list.set_header_func(seperator_headers); this.accounts_list.set_sort_func(ordinal_sort); foreach (Geary.AccountInformation account in accounts.iterable()) { @@ -70,6 +100,15 @@ public class Accounts.Editor : Gtk.Dialog { this.accounts_list.add(new AccountRow(account, status)); } + private void show_account(Geary.AccountInformation account) { + EditorEditPane account_pane = new EditorEditPane( + (GearyApplication) this.application,account + ); + this.editor_panes.add(account_pane); + this.editor_panes.set_visible_child(account_pane); + this.back_button.show(); + } + private AccountRow? get_account_row(Geary.AccountInformation account) { AccountRow? row = null; this.accounts_list.foreach((child) => { @@ -101,12 +140,30 @@ public class Accounts.Editor : Gtk.Dialog { } } + [GtkCallback] + private void on_accounts_list_row_activated(Gtk.ListBoxRow activated) { + AccountRow? row = activated as AccountRow; + if (row != null) { + show_account(row.account); + } + } + + [GtkCallback] + private void on_back_button_clicked() { + Gtk.Widget visible_pane = this.editor_panes.get_visible_child(); + if (visible_pane != list_pane) { + this.editor_panes.remove(visible_pane); + } else { + this.back_button.hide(); + } + } + } -private class Accounts.AccountRow : Gtk.ListBoxRow { +private class Accounts.AccountRow : EditorRow { - public Geary.AccountInformation account; + internal Geary.AccountInformation account; private Gtk.Image unavailable_icon = new Gtk.Image.from_icon_name( "dialog-warning-symbolic", Gtk.IconSize.BUTTON @@ -118,20 +175,16 @@ private class Accounts.AccountRow : Gtk.ListBoxRow { public AccountRow(Geary.AccountInformation account, AccountManager.Status status) { this.account = account; - get_style_context().add_class("geary-settings"); - - this.unavailable_icon.no_show_all = true; + this.account_name.show(); this.account_name.set_hexpand(true); this.account_name.halign = Gtk.Align.START; - Gtk.Grid layout = new Gtk.Grid(); - layout.orientation = Gtk.Orientation.HORIZONTAL; - layout.add(this.unavailable_icon); - layout.add(this.account_name); - layout.add(this.account_details); + this.account_details.show(); - add(layout); + this.layout.add(this.unavailable_icon); + this.layout.add(this.account_name); + this.layout.add(this.account_details); update(status); } @@ -187,25 +240,3 @@ private class Accounts.AccountRow : Gtk.ListBoxRow { } } - -private class Accounts.AddRow : Gtk.ListBoxRow { - - - public AddRow() { - get_style_context().add_class("geary-settings"); - - Gtk.Image add_icon = new Gtk.Image.from_icon_name( - "list-add-symbolic", Gtk.IconSize.BUTTON - ); - add_icon.set_hexpand(true); - - Gtk.Grid layout = new Gtk.Grid(); - layout.orientation = Gtk.Orientation.HORIZONTAL; - - layout.add(add_icon); - - add(layout); - } - - -} diff --git a/src/client/application/geary-application.vala b/src/client/application/geary-application.vala index d3cf494b..96e831dc 100644 --- a/src/client/application/geary-application.vala +++ b/src/client/application/geary-application.vala @@ -422,10 +422,7 @@ public class GearyApplication : Gtk.Application { } private void on_activate_accounts() { - Accounts.Editor editor = new Accounts.Editor( - this.controller.account_manager, get_active_window() - ); - editor.show_all(); + Accounts.Editor editor = new Accounts.Editor(this, get_active_window()); editor.run(); editor.destroy(); } diff --git a/src/client/meson.build b/src/client/meson.build index 906a274e..e248cf2e 100644 --- a/src/client/meson.build +++ b/src/client/meson.build @@ -20,6 +20,8 @@ geary_client_vala_sources = files( 'accounts/account-manager.vala', 'accounts/account-spinner-page.vala', 'accounts/accounts-editor.vala', + 'accounts/accounts-editor-edit-pane.vala', + 'accounts/accounts-editor-row.vala', 'accounts/add-edit-page.vala', 'accounts/goa-service-information.vala', 'accounts/local-service-information.vala', diff --git a/ui/accounts_editor.ui b/ui/accounts_editor.ui index 7750d947..e15b5fd9 100644 --- a/ui/accounts_editor.ui +++ b/ui/accounts_editor.ui @@ -13,7 +13,6 @@ False vertical - 2 False @@ -32,11 +31,12 @@ - + True False + slide-left-right - + True False @@ -59,8 +59,8 @@ True False - 32 - 32 + True + True 0 in @@ -69,6 +69,7 @@ True False none + @@ -107,13 +108,43 @@ - - + + + + + + + True + False + Accounts + False + True + + True False - Accounts - True + + + True + True + + + + True + False + True + go-previous-symbolic + + + + + 0 + 0 + + - + diff --git a/ui/accounts_editor_edit_pane.ui b/ui/accounts_editor_edit_pane.ui new file mode 100644 index 00000000..5e0ce99b --- /dev/null +++ b/ui/accounts_editor_edit_pane.ui @@ -0,0 +1,213 @@ + + + + + + diff --git a/ui/geary.css b/ui/geary.css index e34940e5..320b4f86 100644 --- a/ui/geary.css +++ b/ui/geary.css @@ -194,6 +194,16 @@ grid.geary-account-view image:dir(rtl) { margin-left: 6px; } -row.geary-settings { - padding: 16px; +label.geary-settings-heading { + font-weight: bold; + margin-top: 24px; + margin-bottom: 12px; +} + +row.geary-settings { + padding: 18px; +} + +buttonbox.geary-settings { + margin-top: 36px; } diff --git a/ui/org.gnome.Geary.gresource.xml b/ui/org.gnome.Geary.gresource.xml index 9b8e3bd2..975dbde7 100644 --- a/ui/org.gnome.Geary.gresource.xml +++ b/ui/org.gnome.Geary.gresource.xml @@ -5,6 +5,7 @@ account_list.glade account_spinner.glade accounts_editor.ui + accounts_editor_edit_pane.ui certificate_warning_dialog.glade client-web-view.js client-web-view-allow-remote-images.js