[geary/wip/account-editor-refinements-v1: 5/7] Allow adding/modifying an account to be cancelled when in progress
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/account-editor-refinements-v1: 5/7] Allow adding/modifying an account to be cancelled when in progress
- Date: Wed, 9 Jan 2019 02:33:00 +0000 (UTC)
commit cc07e542acfac540b1e7be5ac8a69b552e9ec045
Author: Michael Gratton <mike vee net>
Date: Wed Jan 9 12:23:12 2019 +1100
Allow adding/modifying an account to be cancelled when in progress
This adds a cancellable property to each account pane and uses it for
all I/O operations, and allows it to be cancelled and pane state to be
updated when either Esc is pressed, or Cancel is clicked on the servers
pane.
src/client/accounts/accounts-editor-add-pane.vala | 42 ++++--
src/client/accounts/accounts-editor-edit-pane.vala | 41 ++++--
src/client/accounts/accounts-editor-list-pane.vala | 26 ++--
.../accounts/accounts-editor-remove-pane.vala | 10 +-
.../accounts/accounts-editor-servers-pane.vala | 154 ++++++++++++++++-----
src/client/accounts/accounts-editor.vala | 81 +++++++++--
6 files changed, 278 insertions(+), 76 deletions(-)
---
diff --git a/src/client/accounts/accounts-editor-add-pane.vala
b/src/client/accounts/accounts-editor-add-pane.vala
index 3d7a5610..3c5468df 100644
--- a/src/client/accounts/accounts-editor-add-pane.vala
+++ b/src/client/accounts/accounts-editor-add-pane.vala
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Michael Gratton <mike vee net>
+ * Copyright 2018-2019 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.
@@ -16,6 +16,17 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
get { return this.real_name.value; }
}
+ /** {@inheritDoc} */
+ internal bool is_operation_running {
+ get { return !this.sensitive; }
+ protected set { update_operation_ui(value); }
+ }
+
+ /** {@inheritDoc} */
+ internal GLib.Cancellable? op_cancellable {
+ get; protected set; default = new GLib.Cancellable();
+ }
+
protected weak Accounts.Editor editor { get; set; }
private Geary.ServiceProvider provider;
@@ -51,6 +62,9 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
[GtkChild]
private Gtk.Button create_button;
+ [GtkChild]
+ private Gtk.Button back_button;
+
[GtkChild]
private Gtk.Spinner create_spinner;
@@ -146,10 +160,7 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
}
private async void validate_account(GLib.Cancellable? cancellable) {
- this.create_spinner.show();
- this.create_spinner.start();
- this.create_button.set_sensitive(false);
- this.set_sensitive(false);
+ this.is_operation_running = true;
bool is_valid = false;
string message = "";
@@ -182,6 +193,9 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
to_focus = this.imap_login.value;
// Translators: In-app notification label
message = _("Check your receiving login and password");
+ } catch (GLib.IOError.CANCELLED err) {
+ // Nothing to do here, someone just cancelled
+ debug("IMAP validation was cancelled: %s", err.message);
} catch (GLib.Error err) {
debug("Error validating IMAP service: %s", err.message);
this.imap_tls.show();
@@ -210,6 +224,9 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
to_focus = this.smtp_login.value;
// Translators: In-app notification label
message = _("Check your sending login and password");
+ } catch (GLib.IOError.CANCELLED err) {
+ // Nothing to do here, someone just cancelled
+ debug("SMTP validation was cancelled: %s", err.message);
} catch (GLib.Error err) {
debug("Error validating SMTP service: %s", err.message);
this.smtp_tls.show();
@@ -252,10 +269,7 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
}
}
- this.create_spinner.stop();
- this.create_spinner.hide();
- this.create_button.set_sensitive(true);
- this.set_sensitive(true);
+ this.is_operation_running = false;
// Focus and pop up the notification after re-sensitising
// so it actually succeeds.
@@ -357,6 +371,14 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
this.controls_valid = controls_valid;
}
+ private void update_operation_ui(bool is_running) {
+ this.create_spinner.visible = is_running;
+ this.create_spinner.active = is_running;
+ this.create_button.sensitive = !is_running;
+ this.back_button.sensitive = !is_running;
+ this.sensitive = !is_running;
+ }
+
private void on_validated(Components.Validator.Trigger reason) {
check_validation();
if (this.controls_valid && reason == Components.Validator.Trigger.ACTIVATED) {
@@ -399,7 +421,7 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
[GtkCallback]
private void on_create_button_clicked() {
- this.validate_account.begin(null);
+ this.validate_account.begin(this.op_cancellable);
}
[GtkCallback]
diff --git a/src/client/accounts/accounts-editor-edit-pane.vala
b/src/client/accounts/accounts-editor-edit-pane.vala
index a86ff117..d84727f5 100644
--- a/src/client/accounts/accounts-editor-edit-pane.vala
+++ b/src/client/accounts/accounts-editor-edit-pane.vala
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Michael Gratton <mike vee net>
+ * Copyright 2018-2019 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.
@@ -26,6 +26,14 @@ internal class Accounts.EditorEditPane :
get; protected set; default = new Application.CommandStack();
}
+ /** {@inheritDoc} */
+ internal bool is_operation_running { get; protected set; default = false; }
+
+ /** {@inheritDoc} */
+ internal GLib.Cancellable? op_cancellable {
+ get; protected set; default = null;
+ }
+
/** {@inheritDoc} */
protected weak Accounts.Editor editor { get; set; }
@@ -67,7 +75,9 @@ internal class Accounts.EditorEditPane :
this.pane_content.set_focus_vadjustment(this.pane_adjustment);
this.details_list.set_header_func(Editor.seperator_headers);
- this.details_list.add(new DisplayNameRow(account, this.commands));
+ this.details_list.add(
+ new DisplayNameRow(account, this.commands, this.op_cancellable)
+ );
this.senders_list.set_header_func(Editor.seperator_headers);
foreach (Geary.RFC822.MailboxAddress sender in
@@ -85,7 +95,9 @@ internal class Accounts.EditorEditPane :
this.signature_preview.content_loaded.connect(() => {
// Only enable editability after the content has fully
// loaded to avoid the WebProcess crashing.
- this.signature_preview.set_editable.begin(true, null);
+ this.signature_preview.set_editable.begin(
+ true, this.op_cancellable
+ );
});
this.signature_preview.document_modified.connect(() => {
this.signature_changed = true;
@@ -101,7 +113,7 @@ internal class Accounts.EditorEditPane :
new SignatureChangedCommand(
this.signature_preview, account
),
- null
+ this.op_cancellable
);
}
return Gdk.EVENT_PROPAGATE;
@@ -175,7 +187,7 @@ internal class Accounts.EditorEditPane :
this.account,
this.senders_list
),
- null
+ this.op_cancellable
);
}
@@ -187,7 +199,7 @@ internal class Accounts.EditorEditPane :
this.account,
this.senders_list
),
- null
+ this.op_cancellable
);
}
@@ -253,9 +265,12 @@ private class Accounts.DisplayNameRow : AccountRow<EditorEditPane,Gtk.Entry> {
private Application.CommandStack commands;
+ private GLib.Cancellable? cancellable;
+
public DisplayNameRow(Geary.AccountInformation account,
- Application.CommandStack commands) {
+ Application.CommandStack commands,
+ GLib.Cancellable? cancellable) {
base(
account,
// Translators: Label in the account editor for the user's
@@ -265,6 +280,7 @@ private class Accounts.DisplayNameRow : AccountRow<EditorEditPane,Gtk.Entry> {
);
this.activatable = false;
this.commands = commands;
+ this.cancellable = cancellable;
update();
@@ -295,7 +311,7 @@ private class Accounts.DisplayNameRow : AccountRow<EditorEditPane,Gtk.Entry> {
// account.
_("Change account name back to ā%sā")
),
- null
+ this.cancellable
);
}
@@ -335,7 +351,7 @@ private class Accounts.AddMailboxRow : AddRow<EditorEditPane> {
)
)
),
- null
+ pane.op_cancellable
);
popover.popdown();
});
@@ -376,13 +392,14 @@ private class Accounts.MailboxRow : AccountRow<EditorEditPane,Gtk.Label> {
popover.address
)
),
- null
+ pane.op_cancellable
);
popover.popdown();
});
popover.remove_clicked.connect(() => {
pane.commands.execute.begin(
- new RemoveMailboxCommand(this), null
+ new RemoveMailboxCommand(this),
+ pane.op_cancellable
);
popover.popdown();
});
@@ -788,7 +805,7 @@ private class Accounts.EmailPrefetchRow :
get_label(this.account.prefetch_period_days)
)
),
- null
+ pane.op_cancellable
);
});
}
diff --git a/src/client/accounts/accounts-editor-list-pane.vala
b/src/client/accounts/accounts-editor-list-pane.vala
index 5aa0975b..3cc59888 100644
--- a/src/client/accounts/accounts-editor-list-pane.vala
+++ b/src/client/accounts/accounts-editor-list-pane.vala
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Michael Gratton <mike vee net>
+ * Copyright 2018-2019 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.
@@ -28,21 +28,29 @@ internal class Accounts.EditorListPane : Gtk.Grid, EditorPane, CommandPane {
}
- /** {@iinheritDoc} */
+ /** {@inheritDoc} */
internal Gtk.Widget initial_widget {
get {
return this.show_welcome ? this.service_list : this.accounts_list;
}
}
- /** {@iinheritDoc} */
+ /** {@inheritDoc} */
internal Application.CommandStack commands {
get; protected set; default = new Application.CommandStack();
}
+ /** {@inheritDoc} */
+ internal bool is_operation_running { get; protected set; default = false; }
+
+ /** {@inheritDoc} */
+ internal GLib.Cancellable? op_cancellable {
+ get; protected set; default = null;
+ }
+
internal Manager accounts { get; private set; }
- /** {@iinheritDoc} */
+ /** {@inheritDoc} */
protected weak Accounts.Editor editor { get; set; }
private bool show_welcome {
@@ -144,7 +152,7 @@ internal class Accounts.EditorListPane : Gtk.Grid, EditorPane, CommandPane {
if (row != null) {
this.commands.execute.begin(
new RemoveAccountCommand(account, this.accounts),
- null
+ this.op_cancellable
);
}
}
@@ -208,7 +216,7 @@ internal class Accounts.EditorListPane : Gtk.Grid, EditorPane, CommandPane {
new ReorderAccountCommand(
(AccountListRow) source, new_position, this.accounts
),
- null
+ this.op_cancellable
);
}
@@ -217,7 +225,7 @@ internal class Accounts.EditorListPane : Gtk.Grid, EditorPane, CommandPane {
new ReorderAccountCommand(
(AccountListRow) source, target.get_index(), this.accounts
),
- null
+ this.op_cancellable
);
}
@@ -306,7 +314,7 @@ private class Accounts.AccountListRow : AccountRow<EditorListPane,Gtk.Grid> {
// GOA account but it's disabled, so just take people
// directly to the GOA panel
manager.show_goa_account.begin(
- account, null,
+ account, pane.op_cancellable,
(obj, res) => {
try {
manager.show_goa_account.end(res);
@@ -446,7 +454,7 @@ private class Accounts.AddServiceProviderRow : EditorRow<EditorListPane> {
public override void activated(EditorListPane pane) {
pane.accounts.add_goa_account.begin(
- this.provider, null,
+ this.provider, pane.op_cancellable,
(obj, res) => {
bool add_local = false;
try {
diff --git a/src/client/accounts/accounts-editor-remove-pane.vala
b/src/client/accounts/accounts-editor-remove-pane.vala
index 7698f14c..2a6844cd 100644
--- a/src/client/accounts/accounts-editor-remove-pane.vala
+++ b/src/client/accounts/accounts-editor-remove-pane.vala
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Michael Gratton <mike vee net>
+ * Copyright 2018-2019 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.
@@ -23,6 +23,14 @@ internal class Accounts.EditorRemovePane : Gtk.Grid, EditorPane, AccountPane {
get { return this.remove_button; }
}
+ /** {@inheritDoc} */
+ internal bool is_operation_running { get; protected set; default = false; }
+
+ /** {@inheritDoc} */
+ internal GLib.Cancellable? op_cancellable {
+ get; protected set; default = null;
+ }
+
[GtkChild]
private Gtk.HeaderBar header;
diff --git a/src/client/accounts/accounts-editor-servers-pane.vala
b/src/client/accounts/accounts-editor-servers-pane.vala
index 1718ea03..49004cc2 100644
--- a/src/client/accounts/accounts-editor-servers-pane.vala
+++ b/src/client/accounts/accounts-editor-servers-pane.vala
@@ -1,6 +1,6 @@
/*
* Copyright 2016 Software Freedom Conservancy Inc.
- * Copyright 2018 Michael Gratton <mike vee net>
+ * Copyright 2018-2019 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.
@@ -30,6 +30,17 @@ internal class Accounts.EditorServersPane :
get { return this.details_list; }
}
+ /** {@inheritDoc} */
+ internal bool is_operation_running {
+ get { return !this.sensitive; }
+ protected set { update_operation_ui(value); }
+ }
+
+ /** {@inheritDoc} */
+ internal GLib.Cancellable? op_cancellable {
+ get; protected set; default = new GLib.Cancellable();
+ }
+
private Geary.Engine engine;
// These are copies of the originals that can be updated before
@@ -102,7 +113,9 @@ internal class Accounts.EditorServersPane :
service_provider.activatable = false;
add_row(this.details_list, service_provider);
- this.save_drafts = new SaveDraftsRow(this.account, this.commands);
+ this.save_drafts = new SaveDraftsRow(
+ this.account, this.commands, this.op_cancellable
+ );
add_row(this.details_list, this.save_drafts);
// Receiving
@@ -110,19 +123,36 @@ internal class Accounts.EditorServersPane :
this.receiving_list.set_header_func(Editor.seperator_headers);
add_row(
this.receiving_list,
- new ServiceHostRow(account, this.incoming_mutable, this.commands)
+ new ServiceHostRow(
+ account,
+ this.incoming_mutable,
+ this.commands,
+ this.op_cancellable
+ )
);
add_row(
this.receiving_list,
- new ServiceSecurityRow(account, this.incoming_mutable, this.commands)
+ new ServiceSecurityRow(
+ account,
+ this.incoming_mutable,
+ this.commands,
+ this.op_cancellable
+ )
);
this.incoming_password = new ServicePasswordRow(
- account, this.incoming_mutable, this.commands
+ account,
+ this.incoming_mutable,
+ this.commands,
+ this.op_cancellable
);
this.incoming_login = new ServiceLoginRow(
- account, this.incoming_mutable, this.commands, this.incoming_password
+ account,
+ this.incoming_mutable,
+ this.commands,
+ this.op_cancellable,
+ this.incoming_password
);
add_row(this.receiving_list, this.incoming_login);
@@ -133,24 +163,45 @@ internal class Accounts.EditorServersPane :
this.sending_list.set_header_func(Editor.seperator_headers);
add_row(
this.sending_list,
- new ServiceHostRow(account, this.outgoing_mutable, this.commands)
+ new ServiceHostRow(
+ account,
+ this.outgoing_mutable,
+ this.commands,
+ this.op_cancellable
+ )
);
add_row(
this.sending_list,
- new ServiceSecurityRow(account, this.outgoing_mutable, this.commands)
+ new ServiceSecurityRow(
+ account,
+ this.outgoing_mutable,
+ this.commands,
+ this.op_cancellable
+ )
);
this.outgoing_auth = new ServiceOutgoingAuthRow(
- account, this.outgoing_mutable, this.incoming_mutable, this.commands
+ account,
+ this.outgoing_mutable,
+ this.incoming_mutable,
+ this.commands,
+ this.op_cancellable
);
this.outgoing_auth.value.changed.connect(on_outgoing_auth_changed);
add_row(this.sending_list, this.outgoing_auth);
this.outgoing_password = new ServicePasswordRow(
- account, this.outgoing_mutable, this.commands
+ account,
+ this.outgoing_mutable,
+ this.commands,
+ this.op_cancellable
);
this.outgoing_login = new ServiceLoginRow(
- account, this.outgoing_mutable, this.commands, this.outgoing_password
+ account,
+ this.outgoing_mutable,
+ this.commands,
+ this.op_cancellable,
+ this.outgoing_password
);
add_row(this.sending_list, this.outgoing_login);
@@ -185,10 +236,7 @@ internal class Accounts.EditorServersPane :
}
private async void save(GLib.Cancellable? cancellable) {
- this.apply_button.set_sensitive(false);
- this.apply_spinner.show();
- this.apply_spinner.start();
- this.set_sensitive(false);
+ this.is_operation_running = true;
// Only need to validate if a generic account
bool is_valid = true;
@@ -206,6 +254,8 @@ internal class Accounts.EditorServersPane :
}
}
+ this.is_operation_running = false;
+
if (is_valid) {
if (this.save_drafts.value_changed) {
has_changed = true;
@@ -226,14 +276,10 @@ internal class Accounts.EditorServersPane :
// updated already by the command
this.account.save_drafts = this.save_drafts.initial_value;
}
-
- this.apply_spinner.stop();
- this.apply_spinner.hide();
- this.set_sensitive(true);
}
private async bool validate(GLib.Cancellable? cancellable) {
- string message = "";
+ string? message = null;
bool imap_valid = false;
try {
yield this.engine.validate_imap(
@@ -244,6 +290,9 @@ internal class Accounts.EditorServersPane :
debug("Error authenticating IMAP service: %s", err.message);
// Translators: In-app notification label
message = _("Check your receiving login and password");
+ } catch (GLib.IOError.CANCELLED err) {
+ // Nothing to do here, someone just cancelled
+ debug("IMAP validation was cancelled: %s", err.message);
} catch (GLib.Error err) {
debug("Error validating IMAP service: %s", err.message);
// Translators: In-app notification label
@@ -269,6 +318,9 @@ internal class Accounts.EditorServersPane :
this.outgoing_auth.value.source = Geary.Credentials.Requirement.CUSTOM;
// Translators: In-app notification label
message = _("Check your sending login and password");
+ } catch (GLib.IOError.CANCELLED err) {
+ // Nothing to do here, someone just cancelled
+ debug("SMTP validation was cancelled: %s", err.message);
} catch (GLib.Error err) {
debug("Error validating SMTP service: %s", err.message);
// Translators: In-app notification label
@@ -279,7 +331,7 @@ internal class Accounts.EditorServersPane :
bool is_valid = imap_valid && smtp_valid;
debug("Validation complete, is valid: %s", is_valid.to_string());
- if (!is_valid) {
+ if (!is_valid && message != null) {
this.editor.add_notification(
new InAppNotification(
// Translators: In-app notification label, the
@@ -342,6 +394,13 @@ internal class Accounts.EditorServersPane :
);
}
+ private void update_operation_ui(bool is_running) {
+ this.apply_spinner.visible = is_running;
+ this.apply_spinner.active = is_running;
+ this.apply_button.sensitive = !is_running;
+ this.sensitive = !is_running;
+ }
+
private void on_validator_changed() {
this.apply_button.set_sensitive(is_valid());
}
@@ -354,12 +413,16 @@ internal class Accounts.EditorServersPane :
[GtkCallback]
private void on_cancel_button_clicked() {
- this.editor.pop();
+ if (this.is_operation_running) {
+ cancel_operation();
+ } else {
+ this.editor.pop();
+ }
}
[GtkCallback]
private void on_apply_button_clicked() {
- this.save.begin(null);
+ this.save.begin(this.op_cancellable);
}
[GtkCallback]
@@ -447,7 +510,7 @@ private class Accounts.AccountProviderRow :
public override void activated(EditorServersPane pane) {
if (this.accounts.is_goa_account(this.account)) {
this.accounts.show_goa_account.begin(
- account, null,
+ account, pane.op_cancellable,
(obj, res) => {
try {
this.accounts.show_goa_account.end(res);
@@ -476,9 +539,12 @@ private class Accounts.SaveDraftsRow :
public bool initial_value { get; private set; }
private Application.CommandStack commands;
+ private GLib.Cancellable? cancellable;
+
public SaveDraftsRow(Geary.AccountInformation account,
- Application.CommandStack commands) {
+ Application.CommandStack commands,
+ GLib.Cancellable? cancellable) {
Gtk.Switch value = new Gtk.Switch();
base(
account,
@@ -489,6 +555,7 @@ private class Accounts.SaveDraftsRow :
);
update();
this.commands = commands;
+ this.cancellable = cancellable;
this.activatable = false;
this.initial_value = this.account.save_drafts;
this.account.notify["save-drafts"].connect(on_account_changed);
@@ -505,7 +572,7 @@ private class Accounts.SaveDraftsRow :
new Application.PropertyCommand<bool>(
this.account, "save_drafts", this.value.state
),
- null
+ this.cancellable
);
}
}
@@ -532,11 +599,13 @@ private class Accounts.ServiceHostRow :
}
private Application.CommandStack commands;
+ private GLib.Cancellable? cancellable;
public ServiceHostRow(Geary.AccountInformation account,
Geary.ServiceInformation service,
- Application.CommandStack commands) {
+ Application.CommandStack commands,
+ GLib.Cancellable? cancellable) {
string label = "";
switch (service.protocol) {
case Geary.Protocol.IMAP:
@@ -554,6 +623,7 @@ private class Accounts.ServiceHostRow :
base(account, service, label, new Gtk.Entry());
this.commands = commands;
+ this.cancellable = cancellable;
this.activatable = false;
this.validator = new Components.NetworkAddressValidator(this.value);
@@ -588,8 +658,8 @@ private class Accounts.ServiceHostRow :
this.service, "port", port
)
}),
- null
- );
+ this.cancellable
+ );
}
}
@@ -613,16 +683,19 @@ private class Accounts.ServiceSecurityRow :
private Application.CommandStack commands;
+ private GLib.Cancellable? cancellable;
public ServiceSecurityRow(Geary.AccountInformation account,
Geary.ServiceInformation service,
- Application.CommandStack commands) {
+ Application.CommandStack commands,
+ GLib.Cancellable? cancellable) {
TlsComboBox value = new TlsComboBox();
base(account, service, value.label, value);
update();
this.commands = commands;
+ this.cancellable = cancellable;
this.activatable = false;
value.changed.connect(on_value_changed);
}
@@ -655,7 +728,7 @@ private class Accounts.ServiceSecurityRow :
)
});
}
- this.commands.execute.begin(cmd, null);
+ this.commands.execute.begin(cmd, this.cancellable);
}
}
@@ -677,12 +750,14 @@ private class Accounts.ServiceLoginRow :
}
private Application.CommandStack commands;
+ private GLib.Cancellable? cancellable;
private ServicePasswordRow? password_row;
public ServiceLoginRow(Geary.AccountInformation account,
Geary.ServiceInformation service,
Application.CommandStack commands,
+ GLib.Cancellable? cancellable,
ServicePasswordRow? password_row = null) {
base(
account,
@@ -694,6 +769,7 @@ private class Accounts.ServiceLoginRow :
);
this.commands = commands;
+ this.cancellable = cancellable;
this.activatable = false;
this.validator = new Components.Validator(this.value);
this.password_row = password_row;
@@ -737,7 +813,7 @@ private class Accounts.ServiceLoginRow :
});
}
- this.commands.execute.begin(cmd, null);
+ this.commands.execute.begin(cmd, this.cancellable);
}
}
@@ -795,11 +871,13 @@ private class Accounts.ServicePasswordRow :
}
private Application.CommandStack commands;
+ private GLib.Cancellable? cancellable;
public ServicePasswordRow(Geary.AccountInformation account,
Geary.ServiceInformation service,
- Application.CommandStack commands) {
+ Application.CommandStack commands,
+ GLib.Cancellable? cancellable) {
base(
account,
service,
@@ -810,6 +888,7 @@ private class Accounts.ServicePasswordRow :
);
this.commands = commands;
+ this.cancellable = cancellable;
this.activatable = false;
this.value.visibility = false;
this.value.input_purpose = Gtk.InputPurpose.PASSWORD;
@@ -833,7 +912,7 @@ private class Accounts.ServicePasswordRow :
"credentials",
this.service.credentials.copy_with_token(this.value.text)
),
- null
+ this.cancellable
);
}
}
@@ -852,18 +931,21 @@ private class Accounts.ServiceOutgoingAuthRow :
private Application.CommandStack commands;
+ private GLib.Cancellable? cancellable;
private Geary.ServiceInformation imap_service;
public ServiceOutgoingAuthRow(Geary.AccountInformation account,
Geary.ServiceInformation smtp_service,
Geary.ServiceInformation imap_service,
- Application.CommandStack commands) {
+ Application.CommandStack commands,
+ GLib.Cancellable? cancellable) {
OutgoingAuthComboBox value = new OutgoingAuthComboBox();
base(account, smtp_service, value.label, value);
update();
this.commands = commands;
+ this.cancellable = cancellable;
this.imap_service = imap_service;
this.activatable = false;
value.changed.connect(on_value_changed);
@@ -911,7 +993,7 @@ private class Accounts.ServiceOutgoingAuthRow :
);
}
- this.commands.execute.begin(seq, null);
+ this.commands.execute.begin(seq, this.cancellable);
}
}
diff --git a/src/client/accounts/accounts-editor.vala b/src/client/accounts/accounts-editor.vala
index ca8753fc..7b6f0a04 100644
--- a/src/client/accounts/accounts-editor.vala
+++ b/src/client/accounts/accounts-editor.vala
@@ -73,20 +73,53 @@ public class Accounts.Editor : Gtk.Dialog {
bool ret = Gdk.EVENT_PROPAGATE;
// Allow the user to use Esc, Back and Alt+arrow keys to
- // navigate between panes.
- if (get_current_pane() != this.editor_list_pane) {
+ // navigate between panes. If a pane is executing a long
+ // running operation, only allow Esc and use it to cancel the
+ // operation instead.
+ EditorPane? current_pane = get_current_pane();
+ if (current_pane != null &&
+ current_pane != this.editor_list_pane) {
Gdk.ModifierType state = (
event.state & Gtk.accelerator_get_default_mod_mask()
);
bool is_ltr = (get_direction() == Gtk.TextDirection.LTR);
- if (event.keyval == Gdk.Key.Escape ||
- event.keyval == Gdk.Key.Back ||
- (state == Gdk.ModifierType.MOD1_MASK &&
- (is_ltr && event.keyval == Gdk.Key.Left) ||
- (!is_ltr && event.keyval == Gdk.Key.Right))) {
- pop();
+
+ switch (event.keyval) {
+ case Gdk.Key.Escape:
+ if (current_pane.is_operation_running) {
+ current_pane.cancel_operation();
+ } else {
+ pop();
+ }
ret = Gdk.EVENT_STOP;
+ break;
+
+ case Gdk.Key.Back:
+ if (!current_pane.is_operation_running) {
+ pop();
+ ret = Gdk.EVENT_STOP;
+ }
+ break;
+
+ case Gdk.Key.Left:
+ if (!current_pane.is_operation_running &&
+ state == Gdk.ModifierType.MOD1_MASK &&
+ is_ltr) {
+ pop();
+ ret = Gdk.EVENT_STOP;
+ }
+ break;
+
+ case Gdk.Key.Right:
+ if (!current_pane.is_operation_running &&
+ state == Gdk.ModifierType.MOD1_MASK &&
+ !is_ltr) {
+ pop();
+ ret = Gdk.EVENT_STOP;
+ }
+ break;
}
+
}
if (ret != Gdk.EVENT_STOP) {
@@ -222,9 +255,41 @@ internal interface Accounts.EditorPane : Gtk.Grid {
/** The editor displaying this pane. */
internal abstract Gtk.Widget initial_widget { get; }
+ /**
+ * Determines if a long running operation is being executed.
+ *
+ * @see cancel_operation
+ */
+ internal abstract bool is_operation_running { get; protected set; }
+
+ /**
+ * Long running operation cancellable.
+ *
+ * This cancellable must be passed to any long-running operations
+ * involving I/O. If not null and operation is cancelled, the
+ * value should be cancelled and replaced with a new instance.
+ *
+ * @see cancel_operation
+ */
+ internal abstract GLib.Cancellable? op_cancellable { get; protected set; }
+
/** The GTK header bar to display for this pane. */
internal abstract Gtk.HeaderBar get_header();
+ /**
+ * Cancels this pane's current operation, any.
+ *
+ * Sets {@link is_operation_running} to false and if {@link
+ * op_cancellable} is not null, it is cancelled and replaced with
+ * a new instance.
+ */
+ internal void cancel_operation() {
+ this.is_operation_running = false;
+ if (this.op_cancellable != null) {
+ this.op_cancellable.cancel();
+ this.op_cancellable = new GLib.Cancellable();
+ }
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]