[geary/wip/714809-empty] All hooked up, appears to be working as advertised



commit 94ab08ebf92ef3859cac2fca4a4fc3bf62654557
Author: Jim Nelson <jim yorba org>
Date:   Tue Jan 13 13:03:49 2015 -0800

    All hooked up, appears to be working as advertised

 src/client/application/geary-controller.vala       |   75 +++++++++++++++++---
 src/client/components/main-toolbar.vala            |   18 +++--
 src/engine/imap-db/imap-db-folder.vala             |   25 +++++--
 .../replay-ops/imap-engine-empty-folder.vala       |   21 +++---
 4 files changed, 104 insertions(+), 35 deletions(-)
---
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 33404ea..52bb68f 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -2275,25 +2275,80 @@ public class GearyController : Geary.BaseObject {
     }
     
     private void on_empty_spam() {
-        on_empty_trash_or_spam(Geary.SpecialFolderType.SPAM,
-            _("Empty all email from your Spam folder?"), _("Empty Spam"));
+        on_empty_trash_or_spam(Geary.SpecialFolderType.SPAM);
     }
     
     private void on_empty_trash() {
-        on_empty_trash_or_spam(Geary.SpecialFolderType.TRASH,
-            _("Empty all email from your Trash folder?"), _("Empty Trash"));
+        on_empty_trash_or_spam(Geary.SpecialFolderType.TRASH);
     }
     
-    private void on_empty_trash_or_spam(Geary.SpecialFolderType special_folder_type, string primary_q,
-        string ok_text) {
-        ConfirmationDialog dialog = new ConfirmationDialog(main_window, primary_q,
+    private void on_empty_trash_or_spam(Geary.SpecialFolderType special_folder_type) {
+        // Account must be in place, must have the specified special folder type, and that folder
+        // must support Empty in order for this command to proceed
+        if (current_account == null)
+            return;
+        
+        Geary.Folder? folder = null;
+        try {
+            folder = current_account.get_special_folder(special_folder_type);
+        } catch (Error err) {
+            debug("%s: Unable to get special folder %s: %s", current_account.to_string(),
+                special_folder_type.to_string(), err.message);
+            
+            // fall through
+        }
+        
+        if (folder == null)
+            return;
+        
+        Geary.FolderSupport.Empty? emptyable = folder as Geary.FolderSupport.Empty;
+        if (emptyable == null) {
+            debug("%s: Special folder %s (%s) does not support emptying", current_account.to_string(),
+                folder.path.to_string(), special_folder_type.to_string());
+            
+            return;
+        }
+        
+        ConfirmationDialog dialog = new ConfirmationDialog(main_window,
+            _("Empty all email from your %s folder?").printf(special_folder_type.get_display_name()),
             _("This removes the email from Geary and your email server.")
-                + _("  <b>") + _("This cannot be undone.") + _("</b>"),
-            ok_text);
+                + "  <b>" + _("This cannot be undone.") + "</b>",
+            _("Empty %s").printf(special_folder_type.get_display_name()));
         dialog.use_secondary_markup(true);
         dialog.set_focus_response(Gtk.ResponseType.CANCEL);
         
-        dialog.run();
+        if (dialog.run() == Gtk.ResponseType.OK)
+            empty_folder_async.begin(emptyable, cancellable_folder);
+    }
+    
+    private async void empty_folder_async(Geary.FolderSupport.Empty emptyable, Cancellable? cancellable) {
+        try {
+            yield do_empty_folder_async(emptyable, cancellable);
+        } catch (Error err) {
+            // don't report to user if cancelled
+            if (cancellable is IOError.CANCELLED)
+                return;
+            
+            ErrorDialog dialog = new ErrorDialog(main_window,
+                _("Error emptying %s").printf(emptyable.get_display_name()), err.message);
+            dialog.run();
+        }
+    }
+    
+    private async void do_empty_folder_async(Geary.FolderSupport.Empty emptyable, Cancellable? cancellable)
+        throws Error {
+        yield emptyable.open_async(Geary.Folder.OpenFlags.NONE, cancellable);
+        
+        // be sure to close in all code paths
+        try {
+            yield emptyable.empty_folder_async(cancellable);
+        } finally {
+            try {
+                yield emptyable.close_async(null);
+            } catch (Error err) {
+                // ignored
+            }
+        }
     }
     
     private bool current_folder_supports_trash() {
diff --git a/src/client/components/main-toolbar.vala b/src/client/components/main-toolbar.vala
index 56eb493..9dbf2d5 100644
--- a/src/client/components/main-toolbar.vala
+++ b/src/client/components/main-toolbar.vala
@@ -17,6 +17,7 @@ public class MainToolbar : PillHeaderbar {
     
     private Gtk.Button archive_button;
     private Gtk.Button trash_buttons[2];
+    private Gtk.MenuButton empty_buttons[2];
     private Gtk.SearchEntry search_entry = new Gtk.SearchEntry();
     private Geary.ProgressMonitor? search_upgrade_progress_monitor = null;
     private MonitoredProgressBar search_upgrade_progress_bar = new MonitoredProgressBar();
@@ -73,11 +74,12 @@ public class MainToolbar : PillHeaderbar {
         insert.clear();
         insert.add(archive_button = create_toolbar_button(null, GearyController.ACTION_ARCHIVE_MESSAGE, 
true));
         insert.add(trash_buttons[0] = create_toolbar_button(null, GearyController.ACTION_TRASH_MESSAGE, 
true));
-        insert.add(create_menu_button(null, empty_menu, GearyController.ACTION_EMPTY_MENU));
+        insert.add(empty_buttons[0] = create_menu_button(null, empty_menu, 
GearyController.ACTION_EMPTY_MENU));
         Gtk.Box trash_archive_empty = create_pill_buttons(insert);
         insert.clear();
         insert.add(trash_buttons[1] = create_toolbar_button(null, GearyController.ACTION_TRASH_MESSAGE, 
true));
-        Gtk.Box trash = create_pill_buttons(insert, false);
+        insert.add(empty_buttons[1] = create_menu_button(null, empty_menu, 
GearyController.ACTION_EMPTY_MENU));
+        Gtk.Box trash_empty = create_pill_buttons(insert, false);
         
         // Search bar.
         search_entry.width_chars = 28;
@@ -95,7 +97,7 @@ public class MainToolbar : PillHeaderbar {
         // pack_end() ordering is reversed in GtkHeaderBar in 3.12 and above
 #if !GTK_3_12
         add_end(trash_archive_empty);
-        add_end(trash);
+        add_end(trash_empty);
         add_end(search_upgrade_progress_bar);
         add_end(search_entry);
 #endif
@@ -111,7 +113,7 @@ public class MainToolbar : PillHeaderbar {
 #if GTK_3_12
         add_end(search_entry);
         add_end(search_upgrade_progress_bar);
-        add_end(trash);
+        add_end(trash_empty);
         add_end(trash_archive_empty);
 #endif
         
@@ -121,12 +123,12 @@ public class MainToolbar : PillHeaderbar {
     private void show_archive_button(bool show) {
         if (show) {
             archive_button.show();
-            trash_buttons[0].show();
-            trash_buttons[1].hide();
+            trash_buttons[0].visible = empty_buttons[0].visible = true;
+            trash_buttons[1].visible = empty_buttons[1].visible = false;
         } else {
             archive_button.hide();
-            trash_buttons[0].hide();
-            trash_buttons[1].show();
+            trash_buttons[0].visible = empty_buttons[0].visible = false;
+            trash_buttons[1].visible = empty_buttons[1].visible = true;
         }
     }
     
diff --git a/src/engine/imap-db/imap-db-folder.vala b/src/engine/imap-db/imap-db-folder.vala
index f8c41fb..e1b5abe 100644
--- a/src/engine/imap-db/imap-db-folder.vala
+++ b/src/engine/imap-db/imap-db-folder.vala
@@ -1990,13 +1990,19 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
                 attachment_id, filename);
             
             // On the off-chance this is marked for deletion, unmark it
-            stmt = cx.prepare("""
-                DELETE FROM DeleteAttachmentFileTable
-                WHERE filename = ?
-            """);
-            stmt.bind_string(0, saved_file.get_path());
-            
-            stmt.exec(cancellable);
+            try {
+                stmt = cx.prepare("""
+                    DELETE FROM DeleteAttachmentFileTable
+                    WHERE filename = ?
+                """);
+                stmt.bind_string(0, saved_file.get_path());
+                
+                stmt.exec(cancellable);
+            } catch (Error err) {
+                debug("Unable to delete from DeleteAttachmentFileTable: %s", err.message);
+                
+                // not a deal-breaker, fall through
+            }
             
             debug("Saving attachment to %s", saved_file.get_path());
             
@@ -2278,7 +2284,10 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
     }
     
     private int do_get_unread_count_for_ids(Db.Connection cx,
-        Gee.Collection<ImapDB.EmailIdentifier> ids, Cancellable? cancellable) throws Error {
+        Gee.Collection<ImapDB.EmailIdentifier>? ids, Cancellable? cancellable) throws Error {
+        if (ids == null || ids.size == 0)
+            return 0;
+        
         // Fetch flags for each email and update this folder's unread count.
         // (Note that this only flags for emails which have NOT been marked for removal
         // are included.)
diff --git a/src/engine/imap-engine/replay-ops/imap-engine-empty-folder.vala 
b/src/engine/imap-engine/replay-ops/imap-engine-empty-folder.vala
index 9944d74..1cf774a 100644
--- a/src/engine/imap-engine/replay-ops/imap-engine-empty-folder.vala
+++ b/src/engine/imap-engine/replay-ops/imap-engine-empty-folder.vala
@@ -26,22 +26,24 @@ private class Geary.ImapEngine.EmptyFolder : Geary.ImapEngine.SendReplayOperatio
     }
     
     public override async ReplayOperation.Status replay_local_async() throws Error {
-        int remote_count;
-        int last_seen_remote_count;
-        original_count = engine.get_remote_counts(out remote_count, out last_seen_remote_count);
+        original_count = engine.get_remote_counts(null, null);
         
         // because this value is only used for reporting count changes, offer best-possible service
         if (original_count < 0)
             original_count = 0;
         
+        // mark everything in the folder as removed
         removed_ids = yield engine.local_folder.mark_removed_async(null, true, cancellable);
         
-        if (removed_ids != null && removed_ids.size > 0)
-            engine.replay_notify_email_removed(removed_ids);
-        
-        int new_count = Numeric.int_floor(original_count - removed_ids.size, 0);
-        if (new_count != original_count)
-            engine.replay_notify_email_count_changed(new_count, Geary.Folder.CountChangeReason.REMOVED);
+        // if local folder is not empty, report all as being removed
+        if (removed_ids != null) {
+            if (removed_ids.size > 0)
+                engine.replay_notify_email_removed(removed_ids);
+            
+            int new_count = Numeric.int_floor(original_count - removed_ids.size, 0);
+            if (new_count != original_count)
+                engine.replay_notify_email_count_changed(new_count, Geary.Folder.CountChangeReason.REMOVED);
+        }
         
         return ReplayOperation.Status.CONTINUE;
     }
@@ -52,6 +54,7 @@ private class Geary.ImapEngine.EmptyFolder : Geary.ImapEngine.SendReplayOperatio
     }
     
     public override async ReplayOperation.Status replay_remote_async() throws Error {
+        // STORE and EXPUNGE using positional addressing: "1:*"
         Imap.MessageSet msg_set = new Imap.MessageSet.range_to_highest(
             new Imap.SequenceNumber(Imap.SequenceNumber.MIN));
         


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