[geary/wip/720361-stemming] Small updates in preparation for landing this.



commit 4b0a0e99c87b67c26e33682e27fd77953cd6d34a
Author: Jim Nelson <jim yorba org>
Date:   Mon Dec 15 15:35:15 2014 -0800

    Small updates in preparation for landing this.

 src/client/application/geary-controller.vala       |    2 +-
 .../conversation-viewer/conversation-viewer.vala   |   29 +++++++++++--
 src/engine/abstract/geary-abstract-account.vala    |    2 +-
 src/engine/api/geary-account.vala                  |    4 +-
 src/engine/api/geary-search-folder.vala            |   14 +++---
 src/engine/imap-db/imap-db-account.vala            |   46 ++++----------------
 .../imap-engine/imap-engine-generic-account.vala   |    2 +-
 7 files changed, 47 insertions(+), 52 deletions(-)
---
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 97bbeec..39f5c75 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -2512,7 +2512,7 @@ public class GearyController : Geary.BaseObject {
         
         cancel_search(); // Stop any search in progress.
         
-        folder.set_search_query(search_text, GearyApplication.instance.config.get_search_strategy(),
+        folder.search(search_text, GearyApplication.instance.config.get_search_strategy(),
             cancellable_search);
         
         main_window.folder_list.set_search(folder);
diff --git a/src/client/conversation-viewer/conversation-viewer.vala 
b/src/client/conversation-viewer/conversation-viewer.vala
index ce113eb..5bb4847 100644
--- a/src/client/conversation-viewer/conversation-viewer.vala
+++ b/src/client/conversation-viewer/conversation-viewer.vala
@@ -457,11 +457,28 @@ public class ConversationViewer : Gtk.Box {
         }
     }
     
-    private void on_search_text_changed(string? query) {
+    private void on_search_text_changed(Geary.SearchQuery? query) {
         if (query != null)
             highlight_search_terms.begin();
     }
     
+    // This applies a fudge-factor set of matches when the database results
+    // aren't entirely satisfactory, such as when you search for an email
+    // address and the database tokenizes out the @ and ., etc.  It's not meant
+    // to be comprehensive, just a little extra highlighting applied to make
+    // the results look a little closer to what you typed.
+    private void add_literal_matches(string raw_query, Gee.Set<string>? search_matches) {
+        foreach (string word in raw_query.split(" ")) {
+            if (word.has_suffix("\""))
+                word = word.substring(0, word.length - 1);
+            if (word.has_prefix("\""))
+                word = word.substring(1);
+            
+            if (!Geary.String.is_empty_or_whitespace(word))
+                search_matches.add(word);
+        }
+    }
+    
     private async void highlight_search_terms() {
         if (search_folder == null)
             return;
@@ -475,8 +492,13 @@ public class ConversationViewer : Gtk.Box {
             ids.add(email.id);
         
         try {
-            Gee.Collection<string>? search_matches = yield search_folder.get_search_matches_async(
+            Gee.Set<string>? search_matches = yield search_folder.get_search_matches_async(
                 ids, cancellable_fetch);
+            if (search_matches == null)
+                search_matches = new Gee.HashSet<string>();
+            
+            if (search_folder.search_query != null)
+                add_literal_matches(search_folder.search_query.raw, search_matches);
             
             // Webkit's highlighting is ... weird.  In order to actually see
             // all the highlighting you're applying, it seems necessary to
@@ -484,8 +506,7 @@ public class ConversationViewer : Gtk.Box {
             // seems that shorter strings will overwrite longer ones, and
             // you're left with incomplete highlighting.
             Gee.ArrayList<string> ordered_matches = new Gee.ArrayList<string>();
-            if (search_matches != null)
-                ordered_matches.add_all(search_matches);
+            ordered_matches.add_all(search_matches);
             ordered_matches.sort((a, b) => a.length - b.length);
             
             foreach(string match in ordered_matches)
diff --git a/src/engine/abstract/geary-abstract-account.vala b/src/engine/abstract/geary-abstract-account.vala
index 4a224ca..ea24d18 100644
--- a/src/engine/abstract/geary-abstract-account.vala
+++ b/src/engine/abstract/geary-abstract-account.vala
@@ -124,7 +124,7 @@ public abstract class Geary.AbstractAccount : BaseObject, Geary.Account {
         int limit = 100, int offset = 0, Gee.Collection<Geary.FolderPath?>? folder_blacklist = null,
         Gee.Collection<Geary.EmailIdentifier>? search_ids = null, Cancellable? cancellable = null) throws 
Error;
     
-    public abstract async Gee.Collection<string>? get_search_matches_async(Geary.SearchQuery query,
+    public abstract async Gee.Set<string>? get_search_matches_async(Geary.SearchQuery query,
         Gee.Collection<Geary.EmailIdentifier> ids, Cancellable? cancellable = null) throws Error;
     
     public abstract async Gee.MultiMap<Geary.EmailIdentifier, Geary.FolderPath>? 
get_containing_folders_async(
diff --git a/src/engine/api/geary-account.vala b/src/engine/api/geary-account.vala
index c579461..369bf04 100644
--- a/src/engine/api/geary-account.vala
+++ b/src/engine/api/geary-account.vala
@@ -352,9 +352,9 @@ public interface Geary.Account : BaseObject {
         Gee.Collection<Geary.EmailIdentifier>? search_ids = null, Cancellable? cancellable = null) throws 
Error;
     
     /**
-     * Given a list of mail IDs, returns a list of words that match for the query.
+     * Given a list of mail IDs, returns a set of casefolded words that match for the query.
      */
-    public abstract async Gee.Collection<string>? get_search_matches_async(Geary.SearchQuery query,
+    public abstract async Gee.Set<string>? get_search_matches_async(Geary.SearchQuery query,
         Gee.Collection<Geary.EmailIdentifier> ids, Cancellable? cancellable = null) throws Error;
     
     /**
diff --git a/src/engine/api/geary-search-folder.vala b/src/engine/api/geary-search-folder.vala
index 4f51e43..c064a62 100644
--- a/src/engine/api/geary-search-folder.vala
+++ b/src/engine/api/geary-search-folder.vala
@@ -49,6 +49,8 @@ public class Geary.SearchFolder : Geary.AbstractLocalFolder, Geary.FolderSupport
         }
     }
     
+    public Geary.SearchQuery? search_query { get; private set; default = null; }
+    
     private Gee.HashSet<Geary.FolderPath?> exclude_folders = new Gee.HashSet<Geary.FolderPath?>();
     private Geary.SpecialFolderType[] exclude_types = {
         Geary.SpecialFolderType.SPAM,
@@ -56,7 +58,6 @@ public class Geary.SearchFolder : Geary.AbstractLocalFolder, Geary.FolderSupport
         Geary.SpecialFolderType.DRAFTS,
         // Orphan emails (without a folder) are also excluded; see ctor.
     };
-    private Geary.SearchQuery? search_query = null;
     private Gee.TreeSet<ImapDB.SearchEmailIdentifier> search_results;
     private Geary.Nonblocking.Mutex result_mutex = new Geary.Nonblocking.Mutex();
     
@@ -64,7 +65,7 @@ public class Geary.SearchFolder : Geary.AbstractLocalFolder, Geary.FolderSupport
      * Fired when the search query has changed.  This signal is fired *after* the search
      * has completed.
      */
-    public signal void search_query_changed(string? query);
+    public signal void search_query_changed(Geary.SearchQuery? query);
     
     public SearchFolder(Account account) {
         base();
@@ -203,7 +204,7 @@ public class Geary.SearchFolder : Geary.AbstractLocalFolder, Geary.FolderSupport
     /**
      * Sets the keyword string for this search.
      */
-    public void set_search_query(string query, SearchQuery.Strategy strategy, Cancellable? cancellable = 
null) {
+    public void search(string query, SearchQuery.Strategy strategy, Cancellable? cancellable = null) {
         set_search_query_async.begin(query, strategy, cancellable, on_set_search_query_complete);
     }
     
@@ -231,7 +232,7 @@ public class Geary.SearchFolder : Geary.AbstractLocalFolder, Geary.FolderSupport
         result_mutex.release(ref result_mutex_token);
         
         this.search_query = search_query;
-        search_query_changed(search_query.raw);
+        search_query_changed(search_query);
         
         if (error != null)
             throw error;
@@ -426,13 +427,14 @@ public class Geary.SearchFolder : Geary.AbstractLocalFolder, Geary.FolderSupport
     }
     
     /**
-     * Given a list of mail IDs, returns a list of words that match for the current
+     * Given a list of mail IDs, returns a set of casefolded words that match for the current
      * search query.
      */
-    public async Gee.Collection<string>? get_search_matches_async(
+    public async Gee.Set<string>? get_search_matches_async(
         Gee.Collection<Geary.EmailIdentifier> ids, Cancellable? cancellable = null) throws Error {
         if (search_query == null)
             return null;
+        
         return yield account.get_search_matches_async(search_query, ids, cancellable);
     }
     
diff --git a/src/engine/imap-db/imap-db-account.vala b/src/engine/imap-db/imap-db-account.vala
index ac20f8d..9a184d5 100644
--- a/src/engine/imap-db/imap-db-account.vala
+++ b/src/engine/imap-db/imap-db-account.vala
@@ -853,7 +853,7 @@ private class Geary.ImapDB.Account : BaseObject {
                 // some common search phrases we don't respect and therefore don't want to fall
                 // through to search results
                 string lower = s.down();
-                switch (s.down()) {
+                switch (lower) {
                     case "":
                     case "and":
                     case "or":
@@ -886,6 +886,7 @@ private class Geary.ImapDB.Account : BaseObject {
                 // [archive* OR archiv*] when that's the same as [archiv*]), otherwise search for
                 // both
                 string? stemmed = stem_search_term(query, s);
+                
                 string? sql_stemmed = null;
                 if (stemmed != null) {
                     sql_stemmed = "%s*".printf(stemmed);
@@ -930,7 +931,9 @@ private class Geary.ImapDB.Account : BaseObject {
             //
             // Note that this uses SQLite's "standard" query syntax for MATCH, where AND is implied
             // (and would be treated as search term if included), parentheses are not allowed, and
-            // OR has a higher precendence than AND.
+            // OR has a higher precendence than AND.  So the above example in standard syntax is:
+            //
+            // party* OR parti* eventful* OR event*
             StringBuilder builder = new StringBuilder();
             foreach (SearchTerm term in terms) {
                 if (term.sql.size == 0)
@@ -1055,12 +1058,6 @@ private class Geary.ImapDB.Account : BaseObject {
             if (limit > 0)
                 sql.append(" LIMIT ? OFFSET ?");
             
-            StringBuilder builder = new StringBuilder();
-            foreach (string key in query_phrases.keys)
-                builder.append_printf("%s ", query_phrases[key]);
-            
-            debug("\nSEARCH:\n%s\nPHRASES:%s\n", sql.str, builder.str);
-            
             Db.Statement stmt = cx.prepare(sql.str);
             int bind_index = sql_bind_query_phrases(stmt, 0, query_phrases);
             if (limit > 0) {
@@ -1151,28 +1148,8 @@ private class Geary.ImapDB.Account : BaseObject {
         return (search_results.size == 0 ? null : search_results);
     }
     
-    // This applies a fudge-factor set of matches when the database results
-    // aren't entirely satisfactory, such as when you search for an email
-    // address and the database tokenizes out the @ and ., etc.  It's not meant
-    // to be comprehensive, just a little extra highlighting applied to make
-    // the results look a little closer to what you typed.
-    //
-    // TODO: This needs to be done by the client, not the library.
-    /*
-    private void add_literal_matches(string raw_query, Gee.Set<string> search_matches) {
-        foreach (string word in raw_query.split(" ")) {
-            if (word.has_suffix("\""))
-                word = word.substring(0, word.length - 1);
-            if (word.has_prefix("\""))
-                word = word.substring(1);
-            
-            if (!String.is_empty_or_whitespace(word))
-                search_matches.add(word);
-        }
-    }
-    */
-    
-    public async Gee.Collection<string>? get_search_matches_async(Geary.SearchQuery q,
+    // See add_literal_matches() for explanation of include_literal_matches
+    public async Gee.Set<string>? get_search_matches_async(Geary.SearchQuery q,
         Gee.Collection<ImapDB.EmailIdentifier> ids, Cancellable? cancellable = null) throws Error {
         check_open();
         ImapDB.SearchQuery query = check_search_query(q);
@@ -1195,10 +1172,6 @@ private class Geary.ImapDB.Account : BaseObject {
             sql.append(")");
             sql_add_query_phrases(sql, query_phrases);
             
-            StringBuilder builder = new StringBuilder();
-            foreach (string key in query_phrases.keys)
-                builder.append_printf("%s ", query_phrases[key]);
-            
             Db.Statement stmt = cx.prepare(sql.str);
             sql_bind_query_phrases(stmt, 0, query_phrases);
             
@@ -1206,6 +1179,7 @@ private class Geary.ImapDB.Account : BaseObject {
             while (!result.finished) {
                 // Build a list of search offsets.
                 string[] offset_array = result.nonnull_string_at(0).split(" ");
+                
                 Gee.ArrayList<SearchOffset> all_offsets = new Gee.ArrayList<SearchOffset>();
                 int j = 0;
                 while (true) {
@@ -1219,7 +1193,7 @@ private class Geary.ImapDB.Account : BaseObject {
                 // Iterate over the offset list, scrape strings from the database, and push
                 // the results into our return set.
                 foreach(SearchOffset offset in all_offsets) {
-                    string text = result.nonnull_string_at(offset.column + 1);
+                    unowned string text = result.nonnull_string_at(offset.column + 1);
                     search_matches.add(text[offset.byte_offset : offset.byte_offset + offset.size].down());
                 }
                 
@@ -1229,8 +1203,6 @@ private class Geary.ImapDB.Account : BaseObject {
             return Db.TransactionOutcome.DONE;
         }, cancellable);
         
-        //add_literal_matches(query.raw, search_matches);
-        
         return (search_matches.size == 0 ? null : search_matches);
     }
     
diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala 
b/src/engine/imap-engine/imap-engine-generic-account.vala
index 3e6911d..fc7c7e5 100644
--- a/src/engine/imap-engine/imap-engine-generic-account.vala
+++ b/src/engine/imap-engine/imap-engine-generic-account.vala
@@ -837,7 +837,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
         return yield local.search_async(query, limit, offset, folder_blacklist, search_ids, cancellable);
     }
     
-    public override async Gee.Collection<string>? get_search_matches_async(Geary.SearchQuery query,
+    public override async Gee.Set<string>? get_search_matches_async(Geary.SearchQuery query,
         Gee.Collection<Geary.EmailIdentifier> ids, Cancellable? cancellable = null) throws Error {
         return yield local.get_search_matches_async(query, check_ids(ids), cancellable);
     }


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