Add initial replacement account server details pane.

This commit is contained in:
Michael James Gratton 2018-06-04 18:28:22 +10:00
parent b289170c1a
commit 688040663a
8 changed files with 594 additions and 3 deletions

View file

@ -21,6 +21,7 @@ src/client/accounts/accounts-editor.vala
src/client/accounts/accounts-editor-edit-pane.vala
src/client/accounts/accounts-editor-remove-pane.vala
src/client/accounts/accounts-editor-row.vala
src/client/accounts/accounts-editor-servers-pane.vala
src/client/accounts/add-edit-page.vala
src/client/accounts/editor.vala
src/client/accounts/goa-service-information.vala
@ -413,6 +414,7 @@ ui/account_spinner.glade
ui/accounts_editor.ui
ui/accounts_editor_edit_pane.ui
ui/accounts_editor_remove_pane.ui
ui/accounts_editor_servers_pane.ui
ui/certificate_warning_dialog.glade
ui/composer-headerbar.ui
ui/composer-link-popover.ui

View file

@ -90,7 +90,7 @@ public class Accounts.EditorEditPane : Gtk.Grid {
[GtkCallback]
private void on_server_settings_clicked() {
this.editor.push(new EditorServersPane(this.editor, this.account));
}
[GtkCallback]

View file

@ -55,6 +55,7 @@ internal class Accounts.AddRow : EditorRow {
public AddRow() {
get_style_context().add_class("geary-add-row");
Gtk.Image add_icon = new Gtk.Image.from_icon_name(
"list-add-symbolic", Gtk.IconSize.BUTTON
);

View file

@ -0,0 +1,413 @@
/*
* Copyright 2016 Software Freedom Conservancy Inc.
* Copyright 2018 Michael Gratton <mike@vee.net>
*
* 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_servers_pane.ui")]
public class Accounts.EditorServersPane : Gtk.Grid {
private weak Editor editor; // circular ref
private Geary.AccountInformation account;
[GtkChild]
private Gtk.ListBox details_list;
[GtkChild]
private Gtk.ListBox receiving_list;
[GtkChild]
private Gtk.ListBox sending_list;
public EditorServersPane(Editor editor, Geary.AccountInformation account) {
this.editor = editor;
this.account = account;
this.details_list.set_header_func(Editor.seperator_headers);
this.details_list.add(new ServiceProviderRow(this.account));
// Only add an account provider if it is esoteric enough.
if (this.account.imap.mediator is GoaMediator) {
this.details_list.add(new AccountProviderRow(this.account));
}
this.details_list.add(new EmailPrefetchRow(this.account));
this.details_list.add(new SaveDraftsRow(this.account));
this.receiving_list.set_header_func(Editor.seperator_headers);
build_service(account.imap, this.receiving_list);
this.sending_list.set_header_func(Editor.seperator_headers);
build_service(account.smtp, this.sending_list);
}
private void build_service(Geary.ServiceInformation service,
Gtk.ListBox settings_list) {
settings_list.add(new ServiceHostRow(this.account, service));
settings_list.add(new ServiceSecurityRow(this.account, service));
settings_list.add(new ServiceAuthRow(this.account, service));
}
}
private abstract class Accounts.ServerAccountRow<V> : LabelledEditorRow {
protected Geary.AccountInformation account;
protected V value;
public ServerAccountRow(Geary.AccountInformation account,
string label,
V value) {
base(label);
this.account = account;
set_dim_label(true);
this.value = value;
Gtk.Widget? widget = value as Gtk.Widget;
if (widget != null) {
widget.valign = Gtk.Align.CENTER;
widget.show();
this.layout.add(widget);
}
}
public abstract void update();
}
private class Accounts.ServiceProviderRow : ServerAccountRow<Gtk.Label> {
public ServiceProviderRow(Geary.AccountInformation account) {
base(
account,
// Translators: This label describes service hosting the
// email account, e.g. GMail, Yahoo, Outlook.com, or some
// other generic IMAP service.
_("Service provider"),
new Gtk.Label("")
);
update();
}
public override void update() {
string? details = this.account.service_label;
switch (this.account.service_provider) {
case Geary.ServiceProvider.GMAIL:
details = _("GMail");
break;
case Geary.ServiceProvider.OUTLOOK:
details = _("Outlook.com");
break;
case Geary.ServiceProvider.YAHOO:
details = _("Yahoo");
break;
}
this.value.set_text(details);
// Can't change this, so dim it out
this.value.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
}
}
private class Accounts.AccountProviderRow : ServerAccountRow<Gtk.Label> {
public AccountProviderRow(Geary.AccountInformation account) {
base(
account,
// Translators: This label describes the program that
// created the account, e.g. an SSO service like GOA, or
// locally by Geary.
_("Account source"),
new Gtk.Label("")
);
update();
}
public override void update() {
string? source = null;
if (this.account.imap.mediator is GoaMediator) {
source = _("GNOME Online Accounts");
} else {
source = _("Geary");
}
this.value.set_text(source);
// Can't change this, so dim it out
this.value.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
}
}
private class Accounts.SaveDraftsRow : ServerAccountRow<Gtk.Switch> {
public SaveDraftsRow(Geary.AccountInformation account) {
base(
account,
// Translators: This label describes an account
// preference.
_("Save drafts on server"),
new Gtk.Switch()
);
update();
}
public override void update() {
this.value.state = this.account.save_drafts;
}
}
private class Accounts.EmailPrefetchRow : ServerAccountRow<Gtk.ComboBoxText> {
private static bool row_separator(Gtk.TreeModel model, Gtk.TreeIter iter) {
GLib.Value v;
model.get_value(iter, 0, out v);
return v.get_string() == ".";
}
public EmailPrefetchRow(Geary.AccountInformation account) {
Gtk.ComboBoxText combo = new Gtk.ComboBoxText();
combo.set_row_separator_func(row_separator);
combo.append("14", _("2 weeks back")); // IDs are # of days
combo.append("30", _("1 month back"));
combo.append("90", _("3 months back"));
combo.append("180", _("6 months back"));
combo.append("365", _("1 year back"));
combo.append("730", _("2 years back"));
combo.append("1461", _("4 years back"));
combo.append(".", "."); // Separator
combo.append("-1", _("Everything"));
base(
account,
// Translators: This label describes the account
// preference for the length of time (weeks, months or
// years) that past email should be downloaded.
_("Download mail"),
combo
);
update();
}
public override void update() {
this.value.set_active_id(this.account.prefetch_period_days.to_string());
}
}
private abstract class Accounts.ServerServiceRow<V> : ServerAccountRow<V> {
protected Geary.ServiceInformation service;
public virtual bool is_value_editable {
get {
return (
this.account.service_provider == Geary.ServiceProvider.OTHER &&
!this.is_goa_account
);
}
}
// XXX convenience method until we get a better way of doing this.
protected bool is_goa_account {
get { return (this.service.mediator is GoaMediator); }
}
public ServerServiceRow(Geary.AccountInformation account,
Geary.ServiceInformation service,
string label,
V value) {
base(account, label, value);
this.service = service;
Gtk.Widget? widget = value as Gtk.Widget;
if (widget != null && !this.is_value_editable) {
if (widget is Gtk.Label) {
widget.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
} else {
widget.set_sensitive(false);
}
}
}
}
private class Accounts.ServiceHostRow : ServerServiceRow<Gtk.Label> {
public ServiceHostRow(Geary.AccountInformation account,
Geary.ServiceInformation service) {
string label = _("Unknown");
switch (service.protocol) {
case Geary.Protocol.IMAP:
// Translators: This label describes the host name or IP
// address and port used by an account's IMAP service.
label = _("IMAP server");
break;
case Geary.Protocol.SMTP:
// Translators: This label describes the host name or IP
// address and port used by an account's SMTP service.
label = _("SMTP server");
break;
}
base(
account,
service,
label,
new Gtk.Label("")
);
update();
}
public override void update() {
this.value.set_text(
Geary.String.is_empty(this.service.host)
? _("None")
: "%s:%d".printf(this.service.host, this.service.port)
);
}
}
private class Accounts.ServiceSecurityRow :
ServerServiceRow<Gtk.ComboBoxText> {
private const string INSECURE_ICON = "channel-insecure-symbolic";
private const string SECURE_ICON = "channel-secure-symbolic";
public ServiceSecurityRow(Geary.AccountInformation account,
Geary.ServiceInformation service) {
Gtk.ListStore store = new Gtk.ListStore(
3, typeof(string), typeof(string), typeof(string)
);
Gtk.TreeIter iter;
store.append(out iter);
store.set(iter, 0, "none", 1, INSECURE_ICON, 2, _("None"));
store.append(out iter);
store.set(iter, 0, "start-tls", 1, SECURE_ICON, 2, _("StartTLS"));
store.append(out iter);
store.set(iter, 0, "tls", 1, SECURE_ICON, 2, _("TLS"));
Gtk.ComboBox combo = new Gtk.ComboBox.with_model(store);
combo.set_id_column(0);
Gtk.CellRendererText text_renderer = new Gtk.CellRendererText();
combo.pack_start(text_renderer, true);
combo.add_attribute(text_renderer, "text", 2);
Gtk.CellRendererPixbuf icon_renderer = new Gtk.CellRendererPixbuf();
combo.pack_start(icon_renderer, true);
combo.add_attribute(icon_renderer, "icon_name", 1);
base(
account,
service,
// Translators: This label describes what form of secure
// connection (TLS, StartTLS, etc) used by an account's
// IMAP or SMTP service.
_("Transport security"),
combo
);
update();
}
public override void update() {
if (this.service.use_ssl) {
this.value.set_active_id("tls");
} else if (this.service.use_starttls) {
this.value.set_active_id("start-tls");
} else {
this.value.set_active_id("none");
}
}
}
private class Accounts.ServiceAuthRow : ServerServiceRow<Gtk.Label> {
public ServiceAuthRow(Geary.AccountInformation account,
Geary.ServiceInformation service) {
base(
account,
service,
// Translators: This label describes the authentication
// scheme used by an account's IMAP or SMTP service.
_("Login"),
new Gtk.Label("")
);
update();
}
public override void update() {
string? label = null;
if (this.service.credentials != null) {
string method = _("Unknown");
switch (this.service.credentials.supported_method) {
case Geary.Credentials.Method.PASSWORD:
// Translators: This is used when an account's IMAP or
// SMTP service uses password auth. The string
// replacement is the service's login name.
method = _("%s with password");
break;
case Geary.Credentials.Method.OAUTH2:
// Translators: This is used when an account's IMAP or
// SMTP service uses OAuth2. The string replacement is
// the service's login name.
method = _("%s via OAuth2");
break;
}
string? login = this.service.credentials.user;
if (Geary.String.is_empty(login)) {
login = _("Unknown");
}
label = method.printf(login);
} else if (this.service.protocol == Geary.Protocol.SMTP &&
this.service.smtp_use_imap_credentials) {
label = _("Use IMAP server login");
} else {
// Translators: This is used when no auth scheme is used
// by an account's IMAP or SMTP service.
label = _("None");
}
this.value.set_text(label);
}
}

View file

@ -23,6 +23,7 @@ geary_client_vala_sources = files(
'accounts/accounts-editor-edit-pane.vala',
'accounts/accounts-editor-remove-pane.vala',
'accounts/accounts-editor-row.vala',
'accounts/accounts-editor-servers-pane.vala',
'accounts/add-edit-page.vala',
'accounts/goa-service-information.vala',
'accounts/local-service-information.vala',

View file

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.0 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<template class="AccountsEditorServersPane" parent="GtkGrid">
<property name="name">1</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="hscrollbar_policy">never</property>
<property name="min_content_height">400</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkListBox" id="receiving_list">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="selection_mode">none</property>
</object>
</child>
<child type="label_item">
<placeholder/>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Receiving</property>
<style>
<class name="geary-settings-heading"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkListBox" id="sending_list">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="selection_mode">none</property>
</object>
</child>
<child type="label_item">
<placeholder/>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Sending</property>
<style>
<class name="geary-settings-heading"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkListBox" id="details_list">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="selection_mode">none</property>
</object>
</child>
<child type="label_item">
<placeholder/>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<style>
<class name="geary-account-view"/>
</style>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
</template>
</interface>

View file

@ -200,8 +200,43 @@ label.geary-settings-heading {
margin-bottom: 12px;
}
row.geary-settings {
padding: 18px;
row.geary-settings {
padding: 0px;
}
row.geary-settings > grid > * {
margin: 0px;
padding: 0px;
}
row.geary-settings > grid > * {
margin: 18px 0;
}
row.geary-settings > grid > *:first-child:dir(ltr),
row.geary-settings > grid > *:last-child:dir(rtl) {
margin-left: 18px;
}
row.geary-settings > grid > *:last-child:dir(ltr),
row.geary-settings > grid > *:first-child:dir(rtl) {
margin-right: 18px;
}
row.geary-settings > grid > image:dir(ltr) {
margin-right: 6px;
}
row.geary-settings > grid > image:dir(rtl) {
margin-left: 6px;
}
row.geary-settings > grid > combobox,
row.geary-settings:not(.geary-add-row) > grid > image,
row.geary-settings > grid > switch {
/* These use more space than labels, so set their valign to center
when adding them and free up some space around them here to keep a
consistent row height. */
margin: 0 12px;
}
buttonbox.geary-settings {

View file

@ -7,6 +7,7 @@
<file compressed="true" preprocess="xml-stripblanks">accounts_editor.ui</file>
<file compressed="true" preprocess="xml-stripblanks">accounts_editor_edit_pane.ui</file>
<file compressed="true" preprocess="xml-stripblanks">accounts_editor_remove_pane.ui</file>
<file compressed="true" preprocess="xml-stripblanks">accounts_editor_servers_pane.ui</file>
<file compressed="true" preprocess="xml-stripblanks">certificate_warning_dialog.glade</file>
<file compressed="true">client-web-view.js</file>
<file compressed="true">client-web-view-allow-remote-images.js</file>