Make password dialog HIG-compliant. Closes #5386.

This commit is contained in:
Matthew Pirocchi 2012-06-11 12:20:14 -07:00
parent 2c0a210656
commit e89bb93902
5 changed files with 664 additions and 317 deletions

View file

@ -198,70 +198,67 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
if (username != null) {
Geary.Credentials credentials = new Geary.Credentials(username, null);
old_account_information = new Geary.AccountInformation(credentials);
try {
old_account_information.load_info_from_file();
} catch (Error err) {
debug("Problem loading account information: %s", err.message);
old_account_information = null;
}
old_account_information.load_info_from_file();
}
Geary.AccountInformation account_information =
request_account_information(old_account_information);
do_validate_until_successful_async.begin(account_information, null,
on_do_validate_until_successful_async_finished);
}
private void on_do_validate_until_successful_async_finished(Object? source, AsyncResult result) {
try {
do_validate_until_successful_async.end(result);
} catch (IOError err) {
debug("Caught validation error: %s", err.message);
}
do_validate_until_successful_async.begin(account_information);
}
private async void do_validate_until_successful_async(Geary.AccountInformation account_information,
Cancellable? cancellable = null)
throws IOError {
yield validate_until_successful_async(account_information, cancellable);
Cancellable? cancellable = null) {
Geary.AccountInformation? result = account_information;
do {
result = yield validate_async(result, cancellable);
} while (result != null);
}
private async void validate_until_successful_async(Geary.AccountInformation account_information,
Cancellable? cancellable = null)
throws IOError {
bool success = yield account_information.validate_async(cancellable);
// 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,
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 (success) {
account_information.store_async.begin(cancellable);
try {
set_account(account_information.get_account());
} catch (Error err) {
// TODO: Handle more gracefully
error("Unable to retrieve email account: %s", err.message);
debug("Successfully validated account information");
return null;
} catch (Geary.EngineError err) {
debug("Unable to retrieve email account: %s", err.message);
}
} else {
Geary.AccountInformation new_account_information =
request_account_information(account_information);
// If the user refused to enter account information.
if (new_account_information == null) {
set_account(null);
return;
}
yield validate_until_successful_async(new_account_information, cancellable);
}
debug("Validation failed. Prompting user for revised account information");
Geary.AccountInformation new_account_information =
request_account_information(account_information);
// If the user refused to enter account information. There is currently no way that we
// could see this--we exit in request_account_information, and the only way that an
// exit could be canceled is if there are unsaved composer windows open (which won't
// happen before an account is created). However, best to include this check for the
// future.
if (new_account_information == null) {
set_account(null);
return null;
}
debug("User entered revised account information, retrying validation");
return new_account_information;
}
private void open_account(string username, string? old_password = null, Cancellable? cancellable = null) {
Geary.Credentials credentials = new Geary.Credentials(username, null);
Geary.AccountInformation account_information = new Geary.AccountInformation(credentials);
try {
account_information.load_info_from_file();
} catch (Error err) {
// TODO: Handle this more gracefully?
error("Problem loading account information from file: %s", err.message);
}
account_information.load_info_from_file();
bool remember_password = account_information.remember_password;
string? password = get_password(account_information.credentials.user, old_password, ref remember_password);
@ -278,9 +275,11 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
try {
set_account(account_information.get_account());
} catch (Error err) {
// TODO: Handle more gracefull
error("Unable to retrieve email account: %s", err.message);
} catch (Geary.EngineError err) {
// Our service provider is wrong. But we can't change it, because we don't want to
// change the service provider for an existing account.
debug("Unable to retrieve email account: %s", err.message);
set_account(null);
}
}
@ -318,14 +317,9 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
Geary.Credentials credentials = new Geary.Credentials(username, old_password);
Geary.AccountInformation old_account_information = new Geary.AccountInformation(credentials);
try {
old_account_information.load_info_from_file();
} catch (Error err) {
// TODO: Handle this more gracefully?
error("Error loading account information: %s", err.message);
}
old_account_information.load_info_from_file();
PasswordDialog password_dialog = new PasswordDialog(old_account_information);
PasswordDialog password_dialog = new PasswordDialog(old_account_information, old_password == null);
if (!password_dialog.run()) {
exit(1);
remember_password = false;
@ -353,6 +347,7 @@ along with Geary; if not, write to the Free Software Foundation, Inc.,
new LoginDialog.from_account_information(old_account_information);
if (!login_dialog.show()) {
debug("User refused to enter account information. Exiting...");
exit(1);
return null;
}

View file

@ -28,20 +28,22 @@ public class LoginDialog {
public Geary.AccountInformation account_information { get; private set; }
public LoginDialog.from_account_information(Geary.AccountInformation default_account_information) {
this(default_account_information.real_name, default_account_information.credentials.user,
default_account_information.credentials.pass, default_account_information.remember_password,
default_account_information.service_provider, default_account_information.imap_server_host,
default_account_information.imap_server_port, default_account_information.imap_server_ssl,
default_account_information.smtp_server_host, default_account_information.smtp_server_port,
default_account_information.smtp_server_ssl);
public LoginDialog.from_account_information(Geary.AccountInformation initial_account_information) {
this(initial_account_information.real_name, initial_account_information.credentials.user,
initial_account_information.credentials.pass, initial_account_information.remember_password,
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_smtp_server_host, initial_account_information.default_smtp_server_port,
initial_account_information.default_smtp_server_ssl);
}
public LoginDialog(string? default_real_name = null, string? default_username = null,
string? default_password = null, bool default_remember_password = true, int default_service_provider = -1,
string? default_imap_host = null, uint16 default_imap_port = Geary.Imap.ClientConnection.DEFAULT_PORT_SSL,
bool default_imap_ssl = true, string? default_smtp_host = null,
uint16 default_smtp_port = Geary.Smtp.ClientConnection.DEFAULT_PORT_SSL, bool default_smtp_ssl = true) {
public LoginDialog(string? initial_real_name = null, string? initial_username = null,
string? initial_password = null, bool initial_remember_password = true,
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, string? initial_default_smtp_host = null,
uint16 initial_default_smtp_port = Geary.Smtp.ClientConnection.DEFAULT_PORT_SSL,
bool initial_default_smtp_ssl = true) {
Gtk.Builder builder = GearyApplication.instance.create_builder("login.glade");
dialog = builder.get_object("LoginDialog") as Gtk.Dialog;
@ -66,7 +68,7 @@ public class LoginDialog {
foreach (Geary.ServiceProvider p in Geary.ServiceProvider.get_providers()) {
combo_service.append_text(p.display_name());
if (p == default_service_provider)
if (p == initial_service_provider)
combo_service.set_active(p);
}
@ -74,16 +76,16 @@ public class LoginDialog {
combo_service.set_active(0);
// Set defaults (other than service provider, which is set above)
entry_real_name.set_text(default_real_name ?? "");
entry_username.set_text(default_username ?? "");
entry_password.set_text(default_password ?? "");
check_remember_password.active = default_remember_password;
entry_imap_host.set_text(default_imap_host ?? "");
entry_imap_port.set_text(default_imap_port.to_string());
check_imap_ssl.active = default_imap_ssl;
entry_smtp_host.set_text(default_smtp_host ?? "");
entry_smtp_port.set_text(default_smtp_port.to_string());
check_smtp_ssl.active = default_smtp_ssl;
entry_real_name.set_text(initial_real_name ?? "");
entry_username.set_text(initial_username ?? "");
entry_password.set_text(initial_password ?? "");
check_remember_password.active = initial_remember_password;
entry_imap_host.set_text(initial_default_imap_host ?? "");
entry_imap_port.set_text(initial_default_imap_port.to_string());
check_imap_ssl.active = initial_default_imap_ssl;
entry_smtp_host.set_text(initial_default_smtp_host ?? "");
entry_smtp_port.set_text(initial_default_smtp_port.to_string());
check_smtp_ssl.active = initial_default_smtp_ssl;
if (Geary.String.is_empty(entry_real_name.text))
entry_real_name.grab_focus();
@ -131,12 +133,12 @@ public class LoginDialog {
account_information.real_name = entry_real_name.text.strip();
account_information.remember_password = check_remember_password.active;
account_information.service_provider = get_service_provider();
account_information.imap_server_host = entry_imap_host.text.strip();
account_information.imap_server_port = (uint16) int.parse(entry_imap_port.text.strip());
account_information.imap_server_ssl = check_imap_ssl.active;
account_information.smtp_server_host = entry_smtp_host.text.strip();
account_information.smtp_server_port = (uint16) int.parse(entry_smtp_port.text.strip());
account_information.smtp_server_ssl = check_smtp_ssl.active;
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 = check_imap_ssl.active;
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 = check_smtp_ssl.active;
on_changed();

View file

@ -18,7 +18,7 @@ public class PasswordDialog {
public bool remember_password { get; private set; }
public PasswordDialog(Geary.AccountInformation account_information) {
public PasswordDialog(Geary.AccountInformation account_information, bool first_try) {
Gtk.Builder builder = GearyApplication.instance.create_builder("password-dialog.glade");
// Load dialog
@ -34,14 +34,51 @@ public class PasswordDialog {
Gtk.Label email_label = (Gtk.Label)builder.get_object("email_label");
Gtk.Label real_name_label = (Gtk.Label)builder.get_object("real_name_label");
Gtk.Label service_label = (Gtk.Label)builder.get_object("service_label");
// Load default values
Gtk.Label imap_server_label = (Gtk.Label)builder.get_object("imap_server_label");
Gtk.Label imap_port_label = (Gtk.Label)builder.get_object("imap_port_label");
Gtk.Label imap_encryption_label = (Gtk.Label)builder.get_object("imap_encryption_label");
Gtk.Label smtp_server_label = (Gtk.Label)builder.get_object("smtp_server_label");
Gtk.Label smtp_port_label = (Gtk.Label)builder.get_object("smtp_port_label");
Gtk.Label smtp_encryption_label = (Gtk.Label)builder.get_object("smtp_encryption_label");
// Find server configuration information
Geary.Endpoint imap_endpoint;
Geary.Endpoint smtp_endpoint;
try {
imap_endpoint = account_information.get_imap_endpoint();
smtp_endpoint = account_information.get_smtp_endpoint();
} catch (Geary.EngineError err) {
error("Error getting endpoints: %s", err.message);
}
string imap_server_host = imap_endpoint.host_specifier;
uint16 imap_server_port = imap_endpoint.default_port;
bool imap_server_ssl = (imap_endpoint.flags & Geary.Endpoint.Flags.SSL) != 0;
string smtp_server_host = smtp_endpoint.host_specifier;
uint16 smtp_server_port = smtp_endpoint.default_port;
bool smtp_server_ssl= (smtp_endpoint.flags & Geary.Endpoint.Flags.SSL) != 0;
// Load initial values
email_label.set_text(account_information.credentials.user ?? "");
password_entry.set_text(account_information.credentials.pass ?? "");
remember_password_checkbutton.active = account_information.remember_password;
real_name_label.set_text(account_information.real_name ?? "");
service_label.set_text(account_information.service_provider.display_name() ?? "");
imap_server_label.set_text(imap_server_host);
imap_port_label.set_text(imap_server_port.to_string());
imap_encryption_label.set_text(imap_server_ssl ? "on" : "off");
smtp_server_label.set_text(smtp_server_host);
smtp_port_label.set_text(smtp_server_port.to_string());
smtp_encryption_label.set_text(smtp_server_ssl ? "on" : "off");
// Set primary text
Gtk.Label primary_text_label = (Gtk.Label)builder.get_object("primary_text_label");
const string primary_markup_format = """<span weight="bold" size="larger">%s</span>""";
string primary_markup_text = first_try ? _("Please enter your email password") :
_("Unable to login to email server");
primary_text_label.set_markup(primary_markup_format.printf(primary_markup_text));
primary_text_label.use_markup = true;
// Add action buttons
Gtk.Button cancel_button = new Gtk.Button.from_stock(Gtk.Stock.CANCEL);
ok_button = new Gtk.Button.from_stock(Gtk.Stock.OK);

View file

@ -23,16 +23,16 @@ public class Geary.AccountInformation : Object {
internal File? file = null;
public string real_name { get; set; }
public Geary.ServiceProvider service_provider { get; set; }
public string imap_server_host { get; set; default = ""; }
public uint16 imap_server_port { get; set; default = Imap.ClientConnection.DEFAULT_PORT_SSL; }
public bool imap_server_ssl { get; set; default = true; }
public bool imap_server_pipeline { get; set; default = true; }
public string smtp_server_host { get; set; default = ""; }
public uint16 smtp_server_port { get; set; default = Smtp.ClientConnection.DEFAULT_PORT_SSL; }
public bool smtp_server_ssl { get; set; default = true; }
// These properties are only used if the service provider's account type does not override them.
public string default_imap_server_host { get; set; }
public uint16 default_imap_server_port { get; set; }
public bool default_imap_server_ssl { get; set; }
public string default_smtp_server_host { get; set; }
public uint16 default_smtp_server_port { get; set; }
public bool default_smtp_server_ssl { get; set; }
public Geary.Credentials credentials { get; private set; }
public bool remember_password { get; set; default = true; }
@ -43,53 +43,38 @@ public class Geary.AccountInformation : Object {
this.file = settings_dir.get_child(SETTINGS_FILENAME);
}
public void load_info_from_file() throws Error {
public void load_info_from_file() {
KeyFile key_file = new KeyFile();
try {
key_file.load_from_file(file.get_path() ?? "", KeyFileFlags.NONE);
} catch (FileError.NOENT err) {
// The file didn't exist. No big deal -- just means we give you the defaults.
} catch (FileError err) {
// See comment in next catch block.
} catch (KeyFileError err) {
// It's no big deal if we couldn't load the key file -- just means we give you the defaults.
} finally {
real_name = get_string_value(key_file, GROUP, REAL_NAME_KEY);
remember_password = get_bool_value(key_file, GROUP, REMEMBER_PASSWORD_KEY, true);
service_provider = Geary.ServiceProvider.from_string(get_string_value(key_file, GROUP,
SERVICE_PROVIDER_KEY));
imap_server_host = get_string_value(key_file, GROUP, IMAP_HOST);
imap_server_port = get_uint16_value(key_file, GROUP, IMAP_PORT,
Imap.ClientConnection.DEFAULT_PORT_SSL);
imap_server_ssl = get_bool_value(key_file, GROUP, IMAP_SSL, true);
imap_server_pipeline = get_bool_value(key_file, GROUP, IMAP_PIPELINE, true);
smtp_server_host = get_string_value(key_file, GROUP, SMTP_HOST);
smtp_server_port = get_uint16_value(key_file, GROUP, SMTP_PORT,
Geary.Smtp.ClientConnection.DEFAULT_PORT_SSL);
smtp_server_ssl = get_bool_value(key_file, GROUP, SMTP_SSL, true);
if (service_provider == ServiceProvider.OTHER) {
default_imap_server_host = get_string_value(key_file, GROUP, IMAP_HOST);
default_imap_server_port = get_uint16_value(key_file, GROUP, IMAP_PORT,
Imap.ClientConnection.DEFAULT_PORT_SSL);
default_imap_server_ssl = get_bool_value(key_file, GROUP, IMAP_SSL, true);
default_smtp_server_host = get_string_value(key_file, GROUP, SMTP_HOST);
default_smtp_server_port = get_uint16_value(key_file, GROUP, SMTP_PORT,
Geary.Smtp.ClientConnection.DEFAULT_PORT_SSL);
default_smtp_server_ssl = get_bool_value(key_file, GROUP, SMTP_SSL, true);
}
}
}
public async bool validate_async(Cancellable? cancellable = null) throws IOError {
Geary.Endpoint endpoint;
switch (service_provider) {
case ServiceProvider.GMAIL:
endpoint = GmailAccount.IMAP_ENDPOINT;
break;
case ServiceProvider.YAHOO:
endpoint = YahooAccount.IMAP_ENDPOINT;
break;
case ServiceProvider.OTHER:
Endpoint.Flags imap_flags = imap_server_ssl ? Endpoint.Flags.SSL : Endpoint.Flags.NONE;
imap_flags |= Endpoint.Flags.GRACEFUL_DISCONNECT;
endpoint = new Endpoint(imap_server_host, imap_server_port, imap_flags,
Imap.ClientConnection.RECOMMENDED_TIMEOUT_SEC);
break;
default:
assert_not_reached();
}
public async bool validate_async(Cancellable? cancellable = null) throws EngineError {
Geary.Endpoint endpoint = get_imap_endpoint();
Geary.Imap.ClientSessionManager client_session_manager =
new Geary.Imap.ClientSessionManager(endpoint, credentials, this, 0);
@ -108,37 +93,69 @@ public class Geary.AccountInformation : Object {
return false;
}
public Endpoint get_imap_endpoint() throws EngineError {
switch (service_provider) {
case ServiceProvider.GMAIL:
return GmailAccount.IMAP_ENDPOINT;
case ServiceProvider.YAHOO:
return YahooAccount.IMAP_ENDPOINT;
case ServiceProvider.OTHER:
Endpoint.Flags imap_flags = default_imap_server_ssl ? Endpoint.Flags.SSL :
Endpoint.Flags.NONE;
imap_flags |= Endpoint.Flags.GRACEFUL_DISCONNECT;
return new Endpoint(default_imap_server_host, default_imap_server_port,
imap_flags, Imap.ClientConnection.RECOMMENDED_TIMEOUT_SEC);
default:
throw new EngineError.NOT_FOUND("Service provider of type %s not known",
service_provider.to_string());
}
}
public Endpoint get_smtp_endpoint() throws EngineError {
switch (service_provider) {
case ServiceProvider.GMAIL:
return GmailAccount.SMTP_ENDPOINT;
case ServiceProvider.YAHOO:
return YahooAccount.SMTP_ENDPOINT;
case ServiceProvider.OTHER:
Endpoint.Flags smtp_flags = default_smtp_server_ssl ? Endpoint.Flags.SSL :
Endpoint.Flags.NONE;
smtp_flags |= Geary.Endpoint.Flags.GRACEFUL_DISCONNECT;
return new Endpoint(default_smtp_server_host, default_smtp_server_port,
smtp_flags, Smtp.ClientConnection.DEFAULT_TIMEOUT_SEC);
default:
throw new EngineError.NOT_FOUND("Service provider of type %s not known",
service_provider.to_string());
}
}
public Geary.EngineAccount get_account() throws EngineError {
Geary.Sqlite.Account sqlite_account =
new Geary.Sqlite.Account(credentials.user);
Endpoint imap_endpoint = get_imap_endpoint();
Endpoint smtp_endpoint = get_smtp_endpoint();
switch (service_provider) {
case ServiceProvider.GMAIL:
return new GmailAccount("Gmail account %s".printf(credentials.to_string()),
credentials.user, this, Engine.user_data_dir, new Geary.Imap.Account(
GmailAccount.IMAP_ENDPOINT, GmailAccount.SMTP_ENDPOINT, credentials, this),
sqlite_account);
credentials.user, this, Engine.user_data_dir, new Geary.Imap.Account(imap_endpoint,
smtp_endpoint, credentials, this), sqlite_account);
case ServiceProvider.YAHOO:
return new YahooAccount("Yahoo account %s".printf(credentials.to_string()),
credentials.user, this, Engine.user_data_dir, new Geary.Imap.Account(
YahooAccount.IMAP_ENDPOINT, YahooAccount.SMTP_ENDPOINT, credentials, this),
sqlite_account);
credentials.user, this, Engine.user_data_dir, new Geary.Imap.Account(imap_endpoint,
smtp_endpoint, credentials, this), sqlite_account);
case ServiceProvider.OTHER:
Endpoint.Flags imap_flags = imap_server_ssl ? Endpoint.Flags.SSL : Endpoint.Flags.NONE;
imap_flags |= Endpoint.Flags.GRACEFUL_DISCONNECT;
Endpoint.Flags smtp_flags = smtp_server_ssl ? Endpoint.Flags.SSL : Endpoint.Flags.NONE;
smtp_flags |= Geary.Endpoint.Flags.GRACEFUL_DISCONNECT;
Endpoint imap_endpoint = new Endpoint(imap_server_host, imap_server_port,
imap_flags, Imap.ClientConnection.RECOMMENDED_TIMEOUT_SEC);
Endpoint smtp_endpoint = new Endpoint(smtp_server_host, smtp_server_port,
smtp_flags, Smtp.ClientConnection.DEFAULT_TIMEOUT_SEC);
return new OtherAccount("Other account %s".printf(credentials.to_string()),
credentials.user, this, Engine.user_data_dir, new Geary.Imap.Account(imap_endpoint,
smtp_endpoint, credentials, this), sqlite_account);
@ -205,14 +222,17 @@ public class Geary.AccountInformation : Object {
key_file.set_value(GROUP, SERVICE_PROVIDER_KEY, service_provider.to_string());
key_file.set_boolean(GROUP, REMEMBER_PASSWORD_KEY, remember_password);
key_file.set_value(GROUP, IMAP_HOST, imap_server_host);
key_file.set_integer(GROUP, IMAP_PORT, imap_server_port);
key_file.set_boolean(GROUP, IMAP_SSL, imap_server_ssl);
key_file.set_boolean(GROUP, IMAP_PIPELINE, imap_server_pipeline);
key_file.set_value(GROUP, SMTP_HOST, smtp_server_host);
key_file.set_integer(GROUP, SMTP_PORT, smtp_server_port);
key_file.set_boolean(GROUP, SMTP_SSL, smtp_server_ssl);
if (service_provider == ServiceProvider.OTHER) {
key_file.set_value(GROUP, IMAP_HOST, default_imap_server_host);
key_file.set_integer(GROUP, IMAP_PORT, default_imap_server_port);
key_file.set_boolean(GROUP, IMAP_SSL, default_imap_server_ssl);
key_file.set_value(GROUP, SMTP_HOST, default_smtp_server_host);
key_file.set_integer(GROUP, SMTP_PORT, default_smtp_server_port);
key_file.set_boolean(GROUP, SMTP_SSL, default_smtp_server_ssl);
}
string data = key_file.to_data();
string new_etag;

View file

@ -3,110 +3,486 @@
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkDialog" id="PasswordDialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">Login</property>
<property name="border_width">6</property>
<property name="resizable">False</property>
<property name="type_hint">dialog</property>
<property name="has_resize_grip">False</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox1">
<property name="can_focus">False</property>
<property name="margin_top">6</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<property name="spacing">12</property>
<child>
<object class="GtkGrid" id="grid1">
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">2</property>
<property name="column_spacing">4</property>
<property name="border_width">6</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label2">
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Email address:</property>
<property name="yalign">0</property>
<property name="stock">gtk-dialog-authentication</property>
<property name="icon-size">6</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<object class="GtkBox" id="box2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Password:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">password_entry</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="primary_text_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">2.2351741291171123e-10</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">&lt;span weight="bold"size="larger"&gt;Please enter your email password&lt;/span&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<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">Email address:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Password:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">password_entry</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="email_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="xalign">0</property>
<property name="xpad">2</property>
<property name="label" translatable="yes">example@example.com</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="password_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="visibility">False</property>
<property name="invisible_char">•</property>
<property name="activates_default">True</property>
<property name="invisible_char_set">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="remember_password_checkbutton">
<property name="label" translatable="yes">_Remember password</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkExpander" id="expander1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="spacing">6</property>
<child>
<object class="GtkGrid" id="grid2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<child>
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">Service:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="xpad">13</property>
<property name="label" translatable="yes">Real name:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="service_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Service</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="real_name_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Real name</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="ypad">6</property>
<property name="label" translatable="yes">&lt;span weight="bold"&gt;General&lt;/span&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">6</property>
<property name="xalign">0</property>
<property name="ypad">6</property>
<property name="label" translatable="yes">&lt;span weight="bold"&gt;IMAP settings&lt;/span&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">Server:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label9">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">Port:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">5</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label10">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">SSL/TLS encryption:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">6</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="imap_server_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">server</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">4</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="imap_port_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label">1234</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">5</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="imap_encryption_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label">off</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">6</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label11">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">6</property>
<property name="xalign">0</property>
<property name="ypad">6</property>
<property name="label" translatable="yes">&lt;span weight="bold"&gt;SMTP settings&lt;/span&gt;</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">7</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label12">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">Server:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">8</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label13">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">Port:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">9</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label14">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="xpad">12</property>
<property name="label" translatable="yes">SSL/TLS encryption:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">10</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="smtp_server_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label">server</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">8</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="smtp_port_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label">1234</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">9</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="smtp_encryption_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label">off</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">10</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Details</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="email_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="xalign">0</property>
<property name="xpad">2</property>
<property name="label" translatable="yes">example@example.com</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="password_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="visibility">False</property>
<property name="invisible_char">•</property>
<property name="activates_default">True</property>
<property name="invisible_char_set">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="remember_password_checkbutton">
<property name="label" translatable="yes">_Remember password</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="position">0</property>
</packing>
</child>
<child internal-child="action_area">
@ -127,89 +503,6 @@
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkExpander" id="expander1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">2</property>
<property name="column_spacing">4</property>
<child>
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Service:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Real name:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="service_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Service</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="real_name_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Real name</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Details</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</object>