[geary] Remove folders locally that were removed on server



commit aca1e5398472b731d4ad7a10443a133f3aa460c7
Author: Charles Lindsay <chaz yorba org>
Date:   Fri Feb 14 16:03:19 2014 -0800

    Remove folders locally that were removed on server
    
    Closes: bgo #714357

 src/client/application/geary-controller.vala       |   11 +++++++
 .../folder-list/folder-list-account-branch.vala    |    9 ++++++
 src/engine/imap-db/imap-db-account.vala            |   30 ++++++++++++++++++++
 .../imap-engine/imap-engine-generic-account.vala   |   23 ++++++++++++---
 4 files changed, 68 insertions(+), 5 deletions(-)
---
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index a198bcf..c3429af 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -1230,10 +1230,21 @@ public class GearyController : Geary.BaseObject {
         
         if (unavailable != null) {
             foreach (Geary.Folder folder in unavailable) {
+                main_window.folder_list.remove_folder(folder);
+                if (folder.account == current_account) {
+                    if (main_window.main_toolbar.copy_folder_menu.has_folder(folder))
+                        main_window.main_toolbar.copy_folder_menu.remove_folder(folder);
+                    if (main_window.main_toolbar.move_folder_menu.has_folder(folder))
+                        main_window.main_toolbar.move_folder_menu.remove_folder(folder);
+                }
+                
                 if (folder.special_folder_type == Geary.SpecialFolderType.INBOX &&
                     inboxes.has_key(folder.account)) {
+                    inboxes.unset(folder.account);
                     new_messages_monitor.remove_folder(folder);
                 }
+                
+                folder.special_folder_type_changed.disconnect(on_special_folder_type_changed);
             }
         }
     }
diff --git a/src/client/folder-list/folder-list-account-branch.vala 
b/src/client/folder-list/folder-list-account-branch.vala
index f6af521..bda2d54 100644
--- a/src/client/folder-list/folder-list-account-branch.vala
+++ b/src/client/folder-list/folder-list-account-branch.vala
@@ -23,10 +23,13 @@ public class FolderList.AccountBranch : Sidebar.Branch {
         account.information.notify["nickname"].connect(on_nicknamed_changed);
         
         graft(get_root(), user_folder_group);
+        
+        entry_removed.connect(on_entry_removed);
     }
     
     ~AccountBranch() {
         account.information.notify["nickname"].disconnect(on_nicknamed_changed);
+        entry_removed.disconnect(on_entry_removed);
     }
     
     private void on_nicknamed_changed() {
@@ -123,4 +126,10 @@ public class FolderList.AccountBranch : Sidebar.Branch {
         prune(entry);
         folder_entries.unset(folder.path);
     }
+    
+    private void on_entry_removed(Sidebar.Entry entry) {
+        FolderEntry? folder_entry = entry as FolderEntry;
+        if (folder_entry != null && folder_entries.has_key(folder_entry.folder.path))
+            folder_entries.unset(folder_entry.folder.path);
+    }
 }
diff --git a/src/engine/imap-db/imap-db-account.vala b/src/engine/imap-db/imap-db-account.vala
index db21827..1d4c1bb 100644
--- a/src/engine/imap-db/imap-db-account.vala
+++ b/src/engine/imap-db/imap-db-account.vala
@@ -213,6 +213,29 @@ private class Geary.ImapDB.Account : BaseObject {
         }, cancellable);
     }
     
+    public async void delete_folder_async(Geary.Folder folder, Cancellable? cancellable)
+        throws Error {
+        check_open();
+        
+        Geary.FolderPath path = folder.path;
+        
+        yield db.exec_transaction_async(Db.TransactionType.RW, (cx) => {
+            int64 folder_id;
+            do_fetch_folder_id(cx, path, false, out folder_id, cancellable);
+            if (folder_id == Db.INVALID_ROWID)
+                return Db.TransactionOutcome.ROLLBACK;
+            
+            if (do_has_children(cx, folder_id, cancellable)) {
+                debug("Can't delete folder %s because it has children", folder.to_string());
+                return Db.TransactionOutcome.ROLLBACK;
+            }
+            
+            do_delete_folder(cx, folder_id, cancellable);
+            
+            return Db.TransactionOutcome.COMMIT;
+        }, cancellable);
+    }
+    
     /**
      * Only updates folder's STATUS message count, attributes, recent, and unseen; UIDVALIDITY and UIDNEXT
      * updated when the folder is SELECT/EXAMINED (see update_folder_select_examine_async()) unless
@@ -1245,6 +1268,13 @@ private class Geary.ImapDB.Account : BaseObject {
         return do_fetch_folder_id(cx, path.get_parent(), create, out parent_id, cancellable);
     }
     
+    private bool do_has_children(Db.Connection cx, int64 folder_id, Cancellable? cancellable) throws Error {
+        Db.Statement stmt = cx.prepare("SELECT 1 FROM FolderTable WHERE parent_id = ?");
+        stmt.bind_rowid(0, folder_id);
+        Db.Result result = stmt.exec(cancellable);
+        return !result.finished;
+    }
+    
     // Turn the collection of folder paths into actual folder ids.  As a
     // special case, if "folderless" or orphan emails are to be blacklisted,
     // set the out bool to true.
diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala 
b/src/engine/imap-engine/imap-engine-generic-account.vala
index 87741b6..cd3b24c 100644
--- a/src/engine/imap-engine/imap-engine-generic-account.vala
+++ b/src/engine/imap-engine/imap-engine-generic-account.vala
@@ -633,12 +633,25 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
         Gee.Collection<MinimalFolder> engine_added = new Gee.ArrayList<Geary.Folder>();
         engine_added.add_all(build_folders(folders_to_build));
         
-        // TODO: Remove local folders no longer available remotely.
-        foreach (Geary.Folder folder in to_remove)
-            debug(@"Need to remove folder $folder");
+        notify_folders_available_unavailable(null, to_remove);
         
-        if (engine_added.size > 0)
-            notify_folders_added_removed(sort_by_path(engine_added), null);
+        Gee.ArrayList<Geary.Folder> engine_removed = new Gee.ArrayList<Geary.Folder>();
+        
+        // Sort by path length descending, so we always remove children first.
+        to_remove.sort((a, b) => b.path.get_path_length() - a.path.get_path_length());
+        foreach (Geary.Folder folder in to_remove) {
+            try {
+                debug("Locally deleting removed folder %s", folder.to_string());
+                
+                yield local.delete_folder_async(folder, cancellable);
+                engine_removed.add(folder);
+            } catch (Error e) {
+                debug("Unable to locally delete removed folder %s: %s", folder.to_string(), e.message);
+            }
+        }
+        
+        if (engine_added.size > 0 || engine_removed.size > 0)
+            notify_folders_added_removed(sort_by_path(engine_added), sort_by_path(engine_removed));
         
         // report all altered folders
         if (altered_paths.size > 0) {


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