[geary/mjog/account-command-stacks: 20/27] Make Application.Controller commands per-account
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/mjog/account-command-stacks: 20/27] Make Application.Controller commands per-account
- Date: Sat, 26 Oct 2019 05:35:54 +0000 (UTC)
commit 83bcacd032126bd253c578db0486d182e04d21ee
Author: Michael Gratton <mike vee net>
Date: Wed Oct 23 01:17:17 2019 +1100
Make Application.Controller commands per-account
Give each account its own command stack, and use that when executing
commands for an account, since people are unlikely to select a different
account and expect commands for the previous account to work.
src/client/application/application-controller.vala | 59 ++++-----------
src/client/components/main-window.vala | 83 +++++++++++++++++-----
2 files changed, 79 insertions(+), 63 deletions(-)
---
diff --git a/src/client/application/application-controller.vala
b/src/client/application/application-controller.vala
index a904acda..0fc93e1a 100644
--- a/src/client/application/application-controller.vala
+++ b/src/client/application/application-controller.vala
@@ -47,6 +47,11 @@ public class Application.Controller : Geary.BaseObject {
/** The account's contact store */
public Application.ContactStore contacts { get; private set; }
+ /** The account's application command stack. */
+ public Application.CommandStack commands {
+ get; protected set; default = new CommandStack();
+ }
+
/** A cancellable tied to the life-cycle of the account. */
public Cancellable cancellable {
get; private set; default = new Cancellable();
@@ -154,8 +159,6 @@ public class Application.Controller : Geary.BaseObject {
// Null if none selected
private Geary.Folder? current_folder = null;
- private Application.CommandStack commands { get; protected set; }
-
private Cancellable cancellable_folder = new Cancellable();
private Cancellable cancellable_search = new Cancellable();
private Cancellable cancellable_open_account = new Cancellable();
@@ -233,10 +236,8 @@ public class Application.Controller : Geary.BaseObject {
);
this.plugin_manager.load();
- this.commands = new CommandStack();
-
// Create the main window (must be done after creating actions.)
- main_window = new MainWindow(this.application, this.commands);
+ main_window = new MainWindow(this.application);
main_window.retry_service_problem.connect(on_retry_service_problem);
main_window.notify["has-toplevel-focus"].connect(on_has_toplevel_focus);
@@ -319,36 +320,6 @@ public class Application.Controller : Geary.BaseObject {
return this.accounts.get(account);
}
- /** Un-does the last executed application command, if any. */
- public async void undo() {
- this.commands.undo.begin(
- this.open_cancellable,
- (obj, res) => {
- try {
- this.commands.undo.end(res);
- } catch (GLib.Error err) {
- // XXX extract account info somehow
- report_problem(new Geary.ProblemReport(err));
- }
- }
- );
- }
-
- /** Re-does the last undone application command, if any. */
- public async void redo() {
- this.commands.redo.begin(
- this.open_cancellable,
- (obj, res) => {
- try {
- this.commands.redo.end(res);
- } catch (GLib.Error err) {
- // XXX extract account info somehow
- report_problem(new Geary.ProblemReport(err));
- }
- }
- );
- }
-
/** Closes all accounts and windows, releasing held resources. */
public async void close_async() {
// Cancel internal processes early so they don't block
@@ -580,7 +551,7 @@ public class Application.Controller : Geary.BaseObject {
AccountContext? context = this.accounts.get(target.information);
if (context != null) {
- yield this.commands.execute(
+ yield context.commands.execute(
new MarkEmailCommand(
context.emails,
messages,
@@ -620,7 +591,7 @@ public class Application.Controller : Geary.BaseObject {
throws GLib.Error {
AccountContext? context = this.accounts.get(target.information);
if (context != null) {
- yield this.commands.execute(
+ yield context.commands.execute(
new MarkEmailCommand(
context.emails,
messages,
@@ -650,7 +621,7 @@ public class Application.Controller : Geary.BaseObject {
throws GLib.Error {
AccountContext? context = this.accounts.get(source.account.information);
if (context != null) {
- yield this.commands.execute(
+ yield context.commands.execute(
new MoveEmailCommand(
source,
destination,
@@ -690,7 +661,7 @@ public class Application.Controller : Geary.BaseObject {
);
}
- yield this.commands.execute(
+ yield context.commands.execute(
new MoveEmailCommand(
source,
dest,
@@ -730,7 +701,7 @@ public class Application.Controller : Geary.BaseObject {
);
}
- yield this.commands.execute(
+ yield context.commands.execute(
new MoveEmailCommand(
source,
dest,
@@ -763,7 +734,7 @@ public class Application.Controller : Geary.BaseObject {
throws GLib.Error {
AccountContext? context = this.accounts.get(source.account.information);
if (context != null) {
- yield this.commands.execute(
+ yield context.commands.execute(
new CopyEmailCommand(
source,
destination,
@@ -795,7 +766,7 @@ public class Application.Controller : Geary.BaseObject {
throws GLib.Error {
AccountContext? context = this.accounts.get(target.account.information);
if (context != null) {
- yield this.commands.execute(
+ yield context.commands.execute(
new DeleteEmailCommand(
target,
to_in_folder_email_ids(conversations)
@@ -810,7 +781,7 @@ public class Application.Controller : Geary.BaseObject {
throws GLib.Error {
AccountContext? context = this.accounts.get(target.account.information);
if (context != null) {
- yield this.commands.execute(
+ yield context.commands.execute(
new DeleteEmailCommand(target, messages),
context.cancellable
);
@@ -832,7 +803,7 @@ public class Application.Controller : Geary.BaseObject {
);
}
- yield this.commands.execute(
+ yield context.commands.execute(
new EmptyFolderCommand(emptyable),
context.cancellable
);
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index 19b583d2..cdeb3887 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -195,6 +195,8 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
public StatusBar status_bar { get; private set; default = new StatusBar(); }
private MonitoredSpinner spinner = new MonitoredSpinner();
+ private Application.Controller.AccountContext? context = null;
+
private Geary.AggregateProgressMonitor progress_monitor = new Geary.AggregateProgressMonitor();
private GLib.Cancellable action_update_cancellable = new GLib.Cancellable();
@@ -203,8 +205,6 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
private Geary.TimeoutManager update_ui_timeout;
private int64 update_ui_last = 0;
- private Application.CommandStack commands { get; protected set; }
-
[GtkChild]
private Gtk.Box main_layout;
@@ -250,8 +250,7 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
public signal void on_shift_key(bool pressed);
- public MainWindow(GearyApplication application,
- Application.CommandStack commands) {
+ public MainWindow(GearyApplication application) {
Object(
application: application,
show_menubar: false
@@ -266,12 +265,7 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
setup_layout(application.config);
on_change_orientation();
- this.commands = commands;
- this.commands.executed.connect(on_command_execute);
- this.commands.undone.connect(on_command_undo);
- this.commands.redone.connect(on_command_redo);
update_command_actions();
-
update_conversation_actions(NONE);
this.application.engine.account_available.connect(on_account_available);
@@ -377,8 +371,9 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
/** Deselected the currently selected account, if any. */
public void deselect_account() {
+ // XXX do other things like select the first/next most highest
+ // account's inbox?
this.search_bar.set_search_text(""); // Reset search.
- // XXX do other things
}
/** Displays a composer addressed to a specific email address. */
@@ -705,12 +700,47 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
update_headerbar();
}
+ /** Un-does the last executed application command, if any. */
+ private async void undo() {
+ Application.Controller.AccountContext? selected = this.context;
+ if (selected != null) {
+ selected.commands.undo.begin(
+ selected.cancellable,
+ (obj, res) => {
+ try {
+ selected.commands.undo.end(res);
+ } catch (GLib.Error err) {
+ handle_error(selected.account.information, err);
+ }
+ }
+ );
+ }
+ }
+
+ /** Re-does the last undone application command, if any. */
+ private async void redo() {
+ Application.Controller.AccountContext? selected = this.context;
+ if (selected != null) {
+ selected.commands.redo.begin(
+ selected.cancellable,
+ (obj, res) => {
+ try {
+ selected.commands.redo.end(res);
+ } catch (GLib.Error err) {
+ handle_error(selected.account.information, err);
+ }
+ }
+ );
+ }
+ }
+
private void update_command_actions() {
+ Application.Controller.AccountContext? selected = this.context;
get_action(GearyApplication.ACTION_UNDO).set_enabled(
- this.commands.can_undo
+ selected != null && selected.commands.can_undo
);
get_action(GearyApplication.ACTION_REDO).set_enabled(
- this.commands.can_redo
+ selected != null && selected.commands.can_redo
);
}
@@ -791,17 +821,36 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
if (this.selected_account != null) {
this.main_toolbar.copy_folder_menu.clear();
this.main_toolbar.move_folder_menu.clear();
+
+ Application.Controller.AccountContext? context = this.context;
+ if (context != null) {
+ context.commands.executed.disconnect(on_command_execute);
+ context.commands.undone.disconnect(on_command_undo);
+ context.commands.redone.disconnect(on_command_redo);
+ }
+ this.context = null;
}
this.selected_account = account;
this.search_bar.set_account(account);
if (account != null) {
+ this.context = this.application.controller.get_context_for_account(
+ account.information
+ );
+ if (this.context != null) {
+ this.context.commands.executed.connect(on_command_execute);
+ this.context.commands.undone.connect(on_command_undo);
+ this.context.commands.redone.connect(on_command_redo);
+ }
+
foreach (Geary.Folder folder in account.list_folders()) {
this.main_toolbar.copy_folder_menu.add_folder(folder);
this.main_toolbar.move_folder_menu.add_folder(folder);
}
}
+
+ update_command_actions();
}
}
@@ -939,16 +988,12 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
selected
);
- Application.Controller.AccountContext? context =
- this.application.controller.get_context_for_account(
- convo.base_folder.account.information
- );
-
// It's possible for a conversation with zero email to
// be selected, when it has just evaporated after its
// last email was removed but the conversation monitor
// hasn't signalled its removal yet. In this case,
// just don't load it since it will soon disappear.
+ Application.Controller.AccountContext? context = this.context;
if (context != null && convo.get_count() > 0) {
this.conversation_viewer.load_conversation.begin(
convo,
@@ -1381,11 +1426,11 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
// Window-level action callbacks
private void on_undo() {
- this.application.controller.undo.begin();
+ this.undo.begin();
}
private void on_redo() {
- this.application.controller.redo.begin();
+ this.redo.begin();
}
private void on_close() {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]