[geary/mjog/email-templates: 43/72] Application.AccountContext: Add signals for folder context notifications



commit 778cb2d637acf051cf8da76965ba49511ae7964c
Author: Michael Gratton <mike vee net>
Date:   Thu Apr 2 18:57:27 2020 +1100

    Application.AccountContext: Add signals for folder context notifications
    
    Add signals for folder contexts being added and remove, and hence also
    require them to be added and removed in bulk, as collections.
    
    Also, hook MainWindow up to use these signals rather than requiring
    Controller manually manage notifying each main window of each folder
    becoming available/unavailable.

 .../application/application-account-context.vala   | 28 +++++++--
 src/client/application/application-controller.vala | 47 +++++++-------
 .../application/application-main-window.vala       | 72 ++++++++++++----------
 3 files changed, 88 insertions(+), 59 deletions(-)
---
diff --git a/src/client/application/application-account-context.vala 
b/src/client/application/application-account-context.vala
index 5705677e..45ec9970 100644
--- a/src/client/application/application-account-context.vala
+++ b/src/client/application/application-account-context.vala
@@ -70,6 +70,13 @@ internal class Application.AccountContext : Geary.BaseObject {
         new Gee.HashMap<Geary.FolderPath,FolderContext>();
 
 
+    /** Emitted when folders contexts become available. */
+    public signal void folders_available(Gee.Collection<FolderContext> available);
+
+    /** Emitted when folders contexts become available. */
+    public signal void folders_unavailable(Gee.Collection<FolderContext> unavailable);
+
+
     public AccountContext(Geary.Account account,
                           Geary.App.SearchFolder search,
                           Geary.App.EmailStore emails,
@@ -102,6 +109,13 @@ internal class Application.AccountContext : Geary.BaseObject {
         return effective;
     }
 
+    /**
+     * Returns read-only collection of all known folder contexts.
+     */
+    internal Gee.Collection<FolderContext> get_folders() {
+        return this.folders.values.read_only_view;
+    }
+
     /**
      * Returns context for a folder belonging to this context's account.
      */
@@ -114,13 +128,19 @@ internal class Application.AccountContext : Geary.BaseObject {
     }
 
     /** Adds a context for a folder belonging to the account. */
-    internal void add_folder(FolderContext to_add) {
-        this.folders.set(to_add.folder.path, to_add);
+    internal void add_folders(Gee.Collection<FolderContext> to_add) {
+        foreach (var context in to_add) {
+            this.folders.set(context.folder.path, context);
+        }
+        folders_available(to_add);
     }
 
     /** Adds a context for a folder belonging to the account. */
-    internal void remove_folder(FolderContext to_remove) {
-        this.folders.unset(to_remove.folder.path);
+    internal void remove_folders(Gee.Collection<FolderContext> to_remove) {
+        foreach (var context in to_remove) {
+            this.folders.unset(context.folder.path);
+        }
+        folders_unavailable(to_remove);
     }
 
 }
diff --git a/src/client/application/application-controller.vala 
b/src/client/application/application-controller.vala
index 0be69e63..9cfca88f 100644
--- a/src/client/application/application-controller.vala
+++ b/src/client/application/application-controller.vala
@@ -73,7 +73,7 @@ internal class Application.Controller : Geary.BaseObject {
 
     // Avatar store for the application.
     private Application.AvatarStore avatars = new Application.AvatarStore();
-    
+
     // Primary collection of the application's open accounts
     private Gee.Map<Geary.AccountInformation,AccountContext> accounts =
         new Gee.HashMap<Geary.AccountInformation,AccountContext>();
@@ -901,6 +901,11 @@ internal class Application.Controller : Geary.BaseObject {
             smtp.sending_monitor.finish.connect(on_sending_finished);
         }
 
+        // Notify before opening so that listeners have a chance to
+        // hook into it before signals start getting fired by folders
+        // becoming available, etc.
+        account_available(context);
+
         bool retry = false;
         do {
             try {
@@ -927,7 +932,6 @@ internal class Application.Controller : Geary.BaseObject {
             }
         } while (retry);
 
-        account_available(context);
         update_account_status();
     }
 
@@ -938,6 +942,8 @@ internal class Application.Controller : Geary.BaseObject {
             debug("Closing account: %s", context.account.information.id);
             Geary.Account account = context.account;
 
+            account_unavailable(context, is_shutdown);
+
             // Guard against trying to close the account twice
             this.accounts.unset(account.information);
 
@@ -970,8 +976,6 @@ internal class Application.Controller : Geary.BaseObject {
             // status notifications for it
             update_account_status();
 
-            account_unavailable(context, is_shutdown);
-
             // Stop any background processes
             context.search.clear();
             context.contacts.close();
@@ -1246,56 +1250,55 @@ internal class Application.Controller : Geary.BaseObject {
         Geary.Account account,
         Gee.BidirSortedSet<Geary.Folder>? available,
         Gee.BidirSortedSet<Geary.Folder>? unavailable) {
-        AccountContext context = this.accounts.get(account.information);
+        var account_context = this.accounts.get(account.information);
 
         if (available != null && available.size > 0) {
+            var added_contexts = new Gee.LinkedList<FolderContext>();
             foreach (var folder in available) {
                 if (Controller.should_add_folder(available, folder)) {
                     if (folder.used_as == INBOX) {
-                        if (context.inbox == null) {
-                            context.inbox = folder;
+                        if (account_context.inbox == null) {
+                            account_context.inbox = folder;
                         }
                         folder.open_async.begin(
-                            NO_DELAY, context.cancellable
+                            NO_DELAY, account_context.cancellable
                         );
                     }
 
                     var folder_context = new FolderContext(folder);
-                    context.add_folder(folder_context);
-
-                    foreach (MainWindow main in
-                             this.application.get_main_windows()) {
-                        main.add_folder(folder_context);
-                    }
+                    added_contexts.add(folder_context);
                 }
             }
+            if (!added_contexts.is_empty) {
+                account_context.add_folders(added_contexts);
+            }
         }
 
         if (unavailable != null) {
             Gee.BidirIterator<Geary.Folder> unavailable_iterator =
                 unavailable.bidir_iterator();
             bool has_prev = unavailable_iterator.last();
+            var removed_contexts = new Gee.LinkedList<FolderContext>();
             while (has_prev) {
                 Geary.Folder folder = unavailable_iterator.get();
 
                 if (folder.used_as == INBOX) {
-                    context.inbox = null;
+                    account_context.inbox = null;
                 }
 
-                var folder_context = context.get_folder(folder);
+                var folder_context = account_context.get_folder(folder);
                 if (folder_context != null) {
-                    context.remove_folder(folder_context);
-                    foreach (MainWindow main in
-                             this.application.get_main_windows()) {
-                        main.remove_folder(folder_context);
-                    }
+                    removed_contexts.add(folder_context);
                 }
 
                 has_prev = unavailable_iterator.previous();
             }
+            if (!removed_contexts.is_empty) {
+                account_context.remove_folders(removed_contexts);
+            }
 
             // Notify the command stack that folders have gone away
-            context.controller_stack.folders_removed(unavailable);
+            account_context.controller_stack.folders_removed(unavailable);
         }
     }
 
diff --git a/src/client/application/application-main-window.vala 
b/src/client/application/application-main-window.vala
index c058b33a..9fe6ab19 100644
--- a/src/client/application/application-main-window.vala
+++ b/src/client/application/application-main-window.vala
@@ -985,31 +985,6 @@ public class Application.MainWindow :
         return success;
     }
 
-    /** Adds a folder to the window. */
-    internal void add_folder(FolderContext to_add) {
-        this.folder_list.add_folder(to_add);
-        if (to_add.folder.account == this.selected_account) {
-            this.main_toolbar.copy_folder_menu.add_folder(to_add.folder);
-            this.main_toolbar.move_folder_menu.add_folder(to_add.folder);
-        }
-        to_add.folder.use_changed.connect(
-            on_use_changed
-        );
-    }
-
-    /** Removes a folder from the window. */
-    internal void remove_folder(FolderContext to_remove) {
-        Geary.Folder folder = to_remove.folder;
-        folder.use_changed.disconnect(
-            on_use_changed
-        );
-        if (folder.account == this.selected_account) {
-            this.main_toolbar.copy_folder_menu.remove_folder(folder);
-            this.main_toolbar.move_folder_menu.remove_folder(folder);
-        }
-        this.folder_list.remove_folder(to_remove);
-    }
-
     private void add_account(AccountContext to_add) {
         if (!this.accounts.contains(to_add)) {
             this.folder_list.set_user_folders_root_name(
@@ -1024,18 +999,13 @@ public class Application.MainWindow :
                 this.progress_monitor.add(smtp.sending_monitor);
             }
 
+            to_add.folders_available.connect(on_folders_available);
+            to_add.folders_unavailable.connect(on_folders_unavailable);
             to_add.commands.executed.connect(on_command_execute);
             to_add.commands.undone.connect(on_command_undo);
             to_add.commands.redone.connect(on_command_redo);
 
-            foreach (Geary.Folder folder in
-                     Geary.Account.sort_by_path(to_add.account.list_folders())) {
-                var folder_context = to_add.get_folder(folder);
-                if (folder_context != null) {
-                    add_folder(folder_context);
-                }
-            }
-
+            add_folders(to_add.get_folders());
             this.accounts.add(to_add);
         }
     }
@@ -1070,6 +1040,8 @@ public class Application.MainWindow :
             to_remove.commands.executed.disconnect(on_command_execute);
             to_remove.commands.undone.disconnect(on_command_undo);
             to_remove.commands.redone.disconnect(on_command_redo);
+            to_remove.folders_available.disconnect(on_folders_available);
+            to_remove.folders_available.disconnect(on_folders_unavailable);
 
             this.progress_monitor.remove(to_remove.account.background_progress);
             Geary.Smtp.ClientService? smtp = (
@@ -1080,11 +1052,37 @@ public class Application.MainWindow :
             }
 
             // Finally, remove the account and its folders
+            remove_folders(to_remove.get_folders());
             this.folder_list.remove_account(to_remove.account);
             this.accounts.remove(to_remove);
         }
     }
 
+    /** Adds a folder to the window. */
+    private void add_folders(Gee.Collection<FolderContext> to_add) {
+        foreach (var context in to_add) {
+            this.folder_list.add_folder(context);
+            if (context.folder.account == this.selected_account) {
+                this.main_toolbar.copy_folder_menu.add_folder(context.folder);
+                this.main_toolbar.move_folder_menu.add_folder(context.folder);
+            }
+            context.folder.use_changed.connect(on_use_changed);
+        }
+    }
+
+    /** Removes a folder from the window. */
+    private void remove_folders(Gee.Collection<FolderContext> to_remove) {
+        foreach (var context in to_remove) {
+            Geary.Folder folder = context.folder;
+            folder.use_changed.disconnect(on_use_changed);
+            if (folder.account == this.selected_account) {
+                this.main_toolbar.copy_folder_menu.remove_folder(folder);
+                this.main_toolbar.move_folder_menu.remove_folder(folder);
+            }
+            this.folder_list.remove_folder(context);
+        }
+    }
+
     private AccountContext? get_selected_account_context() {
         AccountContext? context = null;
         if (this.selected_account != null) {
@@ -1949,6 +1947,14 @@ public class Application.MainWindow :
         this.remove_account.begin(account, to_select);
     }
 
+    private void on_folders_available(Gee.Collection<FolderContext> available) {
+        add_folders(available);
+    }
+
+    private void on_folders_unavailable(Gee.Collection<FolderContext> unavailable) {
+        remove_folders(unavailable);
+    }
+
     private void on_use_changed(Geary.Folder folder,
                                 Geary.Folder.SpecialUse old_type,
                                 Geary.Folder.SpecialUse new_type) {


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