[geary/wip/714104-refine-account-dialog] Tidy up account editor pane class interfaces and implementations



commit 05ef6f912fdb1be24ca8c4d24704c0c7e9161d18
Author: Michael Gratton <mike vee net>
Date:   Fri Dec 21 11:26:53 2018 +1100

    Tidy up account editor pane class interfaces and implementations
    
    Add a CommandPane interface and update the others to better share common
    code between implementations.

 src/client/accounts/accounts-editor-edit-pane.vala |  72 ++++------
 src/client/accounts/accounts-editor-list-pane.vala |  20 ++-
 .../accounts/accounts-editor-remove-pane.vala      |  21 ++-
 src/client/accounts/accounts-editor-row.vala       |  34 -----
 .../accounts/accounts-editor-servers-pane.vala     |  63 +++------
 src/client/accounts/accounts-editor.vala           | 145 +++++++++++++++++----
 6 files changed, 180 insertions(+), 175 deletions(-)
---
diff --git a/src/client/accounts/accounts-editor-edit-pane.vala 
b/src/client/accounts/accounts-editor-edit-pane.vala
index 081135c8..66439e62 100644
--- a/src/client/accounts/accounts-editor-edit-pane.vala
+++ b/src/client/accounts/accounts-editor-edit-pane.vala
@@ -9,20 +9,24 @@
  * An account editor pane for editing a specific account's preferences.
  */
 [GtkTemplate (ui = "/org/gnome/Geary/accounts_editor_edit_pane.ui")]
-internal class Accounts.EditorEditPane : Gtk.Grid, EditorPane, AccountPane {
+internal class Accounts.EditorEditPane :
+    Gtk.Grid, EditorPane, AccountPane, CommandPane {
 
 
+    /** {@inheritDoc} */
     internal Gtk.Widget initial_widget {
         get { return this.details_list.get_row_at_index(0); }
     }
 
+    /** {@inheritDoc} */
     internal Geary.AccountInformation account { get ; protected set; }
 
-    /** Command stack for edit pane user commands. */
+    /** {@inheritDoc} */
     internal Application.CommandStack commands {
-        get; private set; default = new Application.CommandStack();
+        get; protected set; default = new Application.CommandStack();
     }
 
+    /** {@inheritDoc} */
     protected weak Accounts.Editor editor { get; set; }
 
     [GtkChild]
@@ -117,79 +121,49 @@ internal class Accounts.EditorEditPane : Gtk.Grid, EditorPane, AccountPane {
             !this.editor.accounts.is_goa_account(account)
         );
 
-        this.account.changed.connect(on_account_changed);
-        update_header();
-
-        this.commands.executed.connect(on_command);
-        this.commands.undone.connect(on_command);
-        this.commands.redone.connect(on_command);
+        connect_account_signals();
+        connect_command_signals();
     }
 
     ~EditorEditPane() {
-        this.account.changed.disconnect(on_account_changed);
-
-        this.commands.executed.disconnect(on_command);
-        this.commands.undone.disconnect(on_command);
-        this.commands.redone.disconnect(on_command);
+        disconnect_account_signals();
+        disconnect_command_signals();
     }
 
     internal string? get_default_name() {
         string? name = account.primary_mailbox.name;
 
         if (Geary.String.is_empty_or_whitespace(name)) {
-            name = Environment.get_real_name();
-            if (Geary.String.is_empty(name) || name == "Unknown") {
-                name = null;
-            }
+            name = this.editor.accounts.get_account_name();
         }
 
         return name;
     }
 
+    /** {@inheritDoc} */
     internal Gtk.HeaderBar get_header() {
         return this.header;
     }
 
-    internal void pane_shown() {
-        update_actions();
-    }
-
-    internal void undo() {
-        this.commands.undo.begin(null);
-    }
-
-    internal void redo() {
-        this.commands.redo.begin(null);
+    internal MailboxRow new_mailbox_row(Geary.RFC822.MailboxAddress sender) {
+        MailboxRow row = new MailboxRow(this.account, sender);
+        row.move_to.connect(on_sender_row_moved);
+        row.dropped.connect(on_sender_row_dropped);
+        return row;
     }
 
-    private void update_actions() {
-        this.editor.get_action(GearyController.ACTION_UNDO).set_enabled(
-            this.commands.can_undo
-        );
-        this.editor.get_action(GearyController.ACTION_REDO).set_enabled(
-            this.commands.can_redo
-        );
+    /** {@inheritDoc} */
+    protected void command_executed() {
+        update_command_actions();
 
         Application.Command next_undo = this.commands.peek_undo();
         this.undo_button.set_tooltip_text(
             (next_undo != null && next_undo.undo_label != null)
             ? next_undo.undo_label : ""
         );
-    }
-
-    internal MailboxRow new_mailbox_row(Geary.RFC822.MailboxAddress sender) {
-        MailboxRow row = new MailboxRow(this.account, sender);
-        row.move_to.connect(on_sender_row_moved);
-        row.dropped.connect(on_sender_row_dropped);
-        return row;
-    }
-
-    private void on_account_changed() {
-        update_header();
-    }
 
-    private void on_command() {
-        update_actions();
+        // Ensure the account is notified that is has changed. This
+        // might not be 100% correct, but it's close enough.
         this.account.changed();
     }
 
diff --git a/src/client/accounts/accounts-editor-list-pane.vala 
b/src/client/accounts/accounts-editor-list-pane.vala
index 81b028c8..ae2ad87c 100644
--- a/src/client/accounts/accounts-editor-list-pane.vala
+++ b/src/client/accounts/accounts-editor-list-pane.vala
@@ -9,7 +9,7 @@
  * An account editor pane for listing all known accounts.
  */
 [GtkTemplate (ui = "/org/gnome/Geary/accounts_editor_list_pane.ui")]
-internal class Accounts.EditorListPane : Gtk.Grid, EditorPane {
+internal class Accounts.EditorListPane : Gtk.Grid, EditorPane, CommandPane {
 
 
     private static int ordinal_sort(Gtk.ListBoxRow a, Gtk.ListBoxRow b) {
@@ -28,14 +28,21 @@ internal class Accounts.EditorListPane : Gtk.Grid, EditorPane {
     }
 
 
+    /** {@iinheritDoc} */
     internal Gtk.Widget initial_widget {
         get {
             return this.show_welcome ? this.service_list : this.accounts_list;
         }
     }
 
+    /** {@iinheritDoc} */
+    internal Application.CommandStack commands {
+        get; protected set; default = new Application.CommandStack();
+    }
+
     internal Manager accounts { get; private set; }
 
+    /** {@iinheritDoc} */
     protected weak Accounts.Editor editor { get; set; }
 
     private bool show_welcome {
@@ -44,8 +51,6 @@ internal class Accounts.EditorListPane : Gtk.Grid, EditorPane {
         }
     }
 
-    private Application.CommandStack commands = new Application.CommandStack();
-
     [GtkChild]
     private Gtk.HeaderBar header;
 
@@ -155,14 +160,7 @@ internal class Accounts.EditorListPane : Gtk.Grid, EditorPane {
         }
     }
 
-    internal void undo() {
-        this.commands.undo.begin(null);
-    }
-
-    internal void redo() {
-        this.commands.redo.begin(null);
-    }
-
+    /** {@inheritDoc} */
     internal Gtk.HeaderBar get_header() {
         return this.header;
     }
diff --git a/src/client/accounts/accounts-editor-remove-pane.vala 
b/src/client/accounts/accounts-editor-remove-pane.vala
index 76a67118..7698f14c 100644
--- a/src/client/accounts/accounts-editor-remove-pane.vala
+++ b/src/client/accounts/accounts-editor-remove-pane.vala
@@ -12,13 +12,16 @@
 internal class Accounts.EditorRemovePane : Gtk.Grid, EditorPane, AccountPane {
 
 
-    internal Gtk.Widget initial_widget {
-        get { return this.remove_button; }
-    }
+    /** {@inheritDoc} */
+    internal weak Accounts.Editor editor { get; set; }
 
+    /** {@inheritDoc} */
     internal Geary.AccountInformation account { get ; protected set; }
 
-    protected weak Accounts.Editor editor { get; set; }
+    /** {@inheritDoc} */
+    internal Gtk.Widget initial_widget {
+        get { return this.remove_button; }
+    }
 
     [GtkChild]
     private Gtk.HeaderBar header;
@@ -38,22 +41,18 @@ internal class Accounts.EditorRemovePane : Gtk.Grid, EditorPane, AccountPane {
             this.warning_label.get_text().printf(account.display_name)
         );
 
-        this.account.changed.connect(on_account_changed);
-        update_header();
+        connect_account_signals();
     }
 
     ~EditorRemovePane() {
-        this.account.changed.disconnect(on_account_changed);
+        disconnect_account_signals();
     }
 
+    /** {@inheritDoc} */
     internal Gtk.HeaderBar get_header() {
         return this.header;
     }
 
-    private void on_account_changed() {
-        update_header();
-    }
-
     [GtkCallback]
     private void on_remove_button_clicked() {
         this.editor.remove_account(this.account);
diff --git a/src/client/accounts/accounts-editor-row.vala b/src/client/accounts/accounts-editor-row.vala
index 35a21829..0b201332 100644
--- a/src/client/accounts/accounts-editor-row.vala
+++ b/src/client/accounts/accounts-editor-row.vala
@@ -570,30 +570,8 @@ internal class Accounts.EditorPopover : Gtk.Popover {
         get; private set; default = new Gtk.Grid();
     }
 
-    internal Gee.Collection<Components.Validator> validators {
-        owned get { return this.validator_backing.read_only_view; }
-    }
-
     protected Gtk.Widget popup_focus = null;
 
-    private Gee.Collection<Components.Validator> validator_backing =
-        new Gee.LinkedList<Components.Validator>();
-
-
-    /**
-     * Emitted when a validated widget is activated all are valid.
-     *
-     * This signal will be emitted when all of the following are true:
-     *
-     * 1. At least one validator has been added to the popover
-     * 2. The user activates an entry that is being monitored by a
-     *    validator
-     * 3. The validation for the has completed (i.e. is not in
-     *    progress)
-     * 4. All validators are in the valid state
-     */
-    public override signal void valid_activated();
-
 
     public EditorPopover() {
         get_style_context().add_class("geary-editor");
@@ -637,11 +615,6 @@ internal class Accounts.EditorPopover : Gtk.Popover {
         }
     }
 
-    public void add_validator(Components.Validator validator) {
-        validator.activated.connect(on_validator_activated);
-        this.validator_backing.add(validator);
-    }
-
     public void add_labelled_row(string label, Gtk.Widget value) {
         Gtk.Label label_widget = new Gtk.Label(label);
         label_widget.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
@@ -656,11 +629,4 @@ internal class Accounts.EditorPopover : Gtk.Popover {
         destroy();
     }
 
-    private void on_validator_activated() {
-        if (Geary.traverse(this.validator_backing).all(
-                (v) => v.state == Components.Validator.Validity.VALID)) {
-            valid_activated();
-        }
-    }
-
 }
diff --git a/src/client/accounts/accounts-editor-servers-pane.vala 
b/src/client/accounts/accounts-editor-servers-pane.vala
index 45fa0aa4..12c24362 100644
--- a/src/client/accounts/accounts-editor-servers-pane.vala
+++ b/src/client/accounts/accounts-editor-servers-pane.vala
@@ -10,21 +10,25 @@
  * An account editor pane for editing server details for an account.
  */
 [GtkTemplate (ui = "/org/gnome/Geary/accounts_editor_servers_pane.ui")]
-internal class Accounts.EditorServersPane : Gtk.Grid, EditorPane, AccountPane {
+internal class Accounts.EditorServersPane :
+    Gtk.Grid, EditorPane, AccountPane, CommandPane {
 
 
-    internal Gtk.Widget initial_widget {
-        get { return this.details_list; }
-    }
+    /** {@inheritDoc} */
+    internal weak Accounts.Editor editor { get; set; }
 
+    /** {@inheritDoc} */
     internal Geary.AccountInformation account { get ; protected set; }
 
-    /** Command stack for pane user commands. */
+    /** {@inheritDoc} */
     internal Application.CommandStack commands {
-        get; private set; default = new Application.CommandStack();
+        get; protected set; default = new Application.CommandStack();
     }
 
-    protected weak Accounts.Editor editor { get; set; }
+    /** {@inheritDoc} */
+    internal Gtk.Widget initial_widget {
+        get { return this.details_list; }
+    }
 
     private Geary.Engine engine;
 
@@ -157,34 +161,26 @@ internal class Accounts.EditorServersPane : Gtk.Grid, EditorPane, AccountPane {
 
         // Misc plumbing
 
-        this.account.changed.connect(on_account_changed);
+        connect_account_signals();
+        connect_command_signals();
 
-        this.commands.executed.connect(on_command);
-        this.commands.undone.connect(on_command);
-        this.commands.redone.connect(on_command);
-
-        update_header();
         update_outgoing_auth();
     }
 
     ~EditorServersPane() {
-        this.account.changed.disconnect(on_account_changed);
-
-        this.commands.executed.disconnect(on_command);
-        this.commands.undone.disconnect(on_command);
-        this.commands.redone.disconnect(on_command);
+        disconnect_account_signals();
+        disconnect_command_signals();
     }
 
+    /** {@inheritDoc} */
     internal Gtk.HeaderBar get_header() {
         return this.header;
     }
 
-    internal void undo() {
-        this.commands.undo.begin(null);
-    }
-
-    internal void redo() {
-        this.commands.redo.begin(null);
+    /** {@inheritDoc} */
+    protected void command_executed() {
+        update_command_actions();
+        this.apply_button.set_sensitive(this.commands.can_undo);
     }
 
     private bool is_valid() {
@@ -318,17 +314,6 @@ internal class Accounts.EditorServersPane : Gtk.Grid, EditorPane, AccountPane {
         }
     }
 
-    private void update_actions() {
-        this.editor.get_action(GearyController.ACTION_UNDO).set_enabled(
-            this.commands.can_undo
-        );
-        this.editor.get_action(GearyController.ACTION_REDO).set_enabled(
-            this.commands.can_redo
-        );
-
-        this.apply_button.set_sensitive(this.commands.can_undo);
-    }
-
     private void update_outgoing_auth() {
         this.outgoing_login.set_visible(
             this.outgoing_auth.value.source == CUSTOM
@@ -381,14 +366,6 @@ internal class Accounts.EditorServersPane : Gtk.Grid, EditorPane, AccountPane {
         return ret;
     }
 
-    private void on_account_changed() {
-        update_header();
-    }
-
-    private void on_command() {
-        update_actions();
-    }
-
     private void on_outgoing_auth_changed() {
         update_outgoing_auth();
     }
diff --git a/src/client/accounts/accounts-editor.vala b/src/client/accounts/accounts-editor.vala
index 2c253192..4080164d 100644
--- a/src/client/accounts/accounts-editor.vala
+++ b/src/client/accounts/accounts-editor.vala
@@ -145,25 +145,25 @@ public class Accounts.Editor : Gtk.Dialog {
     }
 
     private void on_undo() {
-        get_current_pane().undo();
+        CommandPane? pane = get_current_pane() as CommandPane;
+        if (pane != null) {
+            pane.undo();
+        }
     }
 
     private void on_redo() {
-        get_current_pane().redo();
+        CommandPane? pane = get_current_pane() as CommandPane;
+        if (pane != null) {
+            pane.redo();
+        }
     }
 
     private void on_pane_changed() {
         EditorPane? visible = get_current_pane();
         Gtk.Widget? header = null;
-        debug(
-            "Have pane: %s, transitions running: %s",
-            (visible != null).to_string(),
-            this.editor_panes.transition_running.to_string()
-        );
         if (visible != null) {
-            visible.pane_shown();
             // Do this in an idle callback since it's not 100%
-            // reliable to just call it here for some reason :(
+            // reliable to just call it here for some reason. :(
             GLib.Idle.add(() => {
                     visible.initial_widget.grab_focus();
                     return GLib.Source.REMOVE;
@@ -171,6 +171,11 @@ public class Accounts.Editor : Gtk.Dialog {
             header = visible.get_header();
         }
         set_titlebar(header);
+
+        CommandPane? commands = visible as CommandPane;
+        if (commands != null) {
+            commands.update_command_actions();
+        }
     }
 
 }
@@ -195,44 +200,130 @@ internal interface Accounts.EditorPane : Gtk.Grid {
 
 
     /** The editor displaying this pane. */
-    internal abstract Gtk.Widget initial_widget { get; }
+    internal abstract weak Accounts.Editor editor { get; set; }
 
     /** The editor displaying this pane. */
-    protected abstract weak Accounts.Editor editor { get; set; }
+    internal abstract Gtk.Widget initial_widget { get; }
 
     /** The GTK header bar to display for this pane. */
     internal abstract Gtk.HeaderBar get_header();
 
-    /** Notifies the pane that it has been displayed in the dialog. */
-    internal virtual void pane_shown() {
-        // no-op by default
+}
+
+
+/**
+ * Interface for editor panes that display a specific account.
+ */
+internal interface Accounts.AccountPane : EditorPane {
+
+
+    /** Account being displayed by this pane. */
+    internal abstract Geary.AccountInformation account { get; protected set; }
+
+
+    /**
+     * Connects to account signals.
+     *
+     * Implementing classes should call this in their constructor.
+     */
+    protected void connect_account_signals() {
+        this.account.changed.connect(on_account_changed);
+        update_header();
     }
 
-    /** Un-does the last user action, if enabled and supported. */
-    internal virtual void undo() {
-        // no-op by default
+    /**
+     * Disconnects from account signals.
+     *
+     * Implementing classes should call this in their destructor.
+     */
+    protected void disconnect_account_signals() {
+        this.account.changed.disconnect(on_account_changed);
     }
 
-    /** Re-does the last user action, if enabled and supported. */
-    internal virtual void redo() {
-        // no-op by default
+    /**
+     * Called when an account has changed.
+     *
+     * By default, updates the editor's header subtitle.
+     */
+    private void account_changed() {
+        update_header();
     }
 
-}
+    private inline void update_header() {
+        get_header().subtitle = this.account.display_name;
+    }
 
+    private void on_account_changed() {
+        account_changed();
+    }
+
+}
 
 /**
- * Base class for editor panes that display a specific account
+ * Interface for editor panes that support undoing/redoing user actions.
  */
-internal interface Accounts.AccountPane : Gtk.Grid, EditorPane {
+internal interface Accounts.CommandPane : EditorPane {
 
 
-    /** Account being displayed by this pane. */
-    internal abstract Geary.AccountInformation account { get; protected set; }
+    /** Stack for the user's commands. */
+    internal abstract Application.CommandStack commands { get; protected set; }
 
 
-    protected void update_header() {
-        get_header().subtitle = this.account.display_name;
+    /** Un-does the last user action, if enabled. */
+    internal virtual void undo() {
+        this.commands.undo.begin(null);
+    }
+
+    /** Re-does the last user action, if enabled. */
+    internal virtual void redo() {
+        this.commands.redo.begin(null);
+    }
+
+    /**
+     * Updates the state of the editor's undo and redo actions.
+     */
+    internal virtual void update_command_actions() {
+        this.editor.get_action(GearyController.ACTION_UNDO).set_enabled(
+            this.commands.can_undo
+        );
+        this.editor.get_action(GearyController.ACTION_REDO).set_enabled(
+            this.commands.can_redo
+        );
+    }
+
+    /**
+     * Connects to command stack signals.
+     *
+     * Implementing classes should call this in their constructor.
+     */
+    protected void connect_command_signals() {
+        this.commands.executed.connect(on_command);
+        this.commands.undone.connect(on_command);
+        this.commands.redone.connect(on_command);
+    }
+
+    /**
+     * Disconnects from command stack signals.
+     *
+     * Implementing classes should call this in their destructor.
+     */
+    protected void disconnect_command_signals() {
+        this.commands.executed.disconnect(on_command);
+        this.commands.undone.disconnect(on_command);
+        this.commands.redone.disconnect(on_command);
+    }
+
+    /**
+     * Called when a command is executed, undone or redone.
+     *
+     * By default, calls {@link update_command_actions}.
+     */
+    protected virtual void command_executed() {
+        update_command_actions();
+    }
+
+    private void on_command() {
+        command_executed();
     }
 
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]