[gnome-shell/zeitgeist: 18/22] Add support for asynchronous search providers



commit 4b015903bc8a957729344e804a7c02ed1aed76ec
Author: Seif Lotfy <seif lotfy com>
Date:   Wed Jan 26 20:43:44 2011 +0100

    Add support for asynchronous search providers
    
    https://bugzilla.gnome.org/show_bug.cgi?id=640659

 js/ui/search.js        |   88 +++++++++++++++++++++++++++++++++++++++--------
 js/ui/searchDisplay.js |   14 +++++---
 js/ui/viewSelector.js  |    2 +-
 3 files changed, 83 insertions(+), 21 deletions(-)
---
diff --git a/js/ui/search.js b/js/ui/search.js
index ca35341..e465a6a 100644
--- a/js/ui/search.js
+++ b/js/ui/search.js
@@ -117,6 +117,43 @@ function SearchProvider(title) {
 SearchProvider.prototype = {
     _init: function(title) {
         this.title = title;
+        this.searchSystem = null;
+        this.searchAsync  = false;
+    },
+
+    _asyncCancelled: function() {
+    },
+
+    startAsync: function() {
+        this.searchAsync = true;
+    },
+
+    tryCancelAsync: function() {
+        if (!this.searchAsync)
+            return;
+        this._asyncCancelled();
+        this.searchAsync = false;
+    },
+
+    /**
+     * addItems:
+     * @items: an array of result identifier strings representing
+     * items which match the last given search terms.
+     *
+     * This should be used for something that requires a bit more
+     * logic; it's designed to be an asyncronous way to add a result
+     * to the current search.
+     */
+    addItems: function( items) {
+        if (!this.searchSystem)
+            throw new Error('Search provider not registered');
+
+        if (!items.length)
+            return;
+
+        this.tryCancelAsync();
+
+        this.searchSystem.addProviderItems(this, items);
     },
 
     /**
@@ -224,6 +261,7 @@ SearchProvider.prototype = {
 };
 Signals.addSignalMethods(SearchProvider.prototype);
 
+
 function OpenSearchSystem() {
     this._init();
 }
@@ -336,6 +374,7 @@ SearchSystem.prototype = {
     },
 
     registerProvider: function (provider) {
+        provider.searchSystem = this;
         this._providers.push(provider);
     },
 
@@ -352,30 +391,50 @@ SearchSystem.prototype = {
         this._previousResults = [];
     },
 
+    addProviderItems: function(provider, items) {
+        let index = this._providers.indexOf(provider);
+        let [provider2, results] = this._previousResults[index];
+        if (provider !== provider2)
+            return;
+
+        results.push.apply(results, items);
+        this.emit('results-updated', this._previousResults);
+    },
+
     updateSearch: function(searchString) {
         searchString = searchString.replace(/^\s+/g, '').replace(/\s+$/g, '');
         if (searchString == '')
-            return [];
+            return;
 
         let terms = searchString.split(/\s+/);
-        let isSubSearch = terms.length == this._previousTerms.length;
-        if (isSubSearch) {
-            for (let i = 0; i < terms.length; i++) {
-                if (terms[i].indexOf(this._previousTerms[i]) != 0) {
-                    isSubSearch = false;
-                    break;
+        this.updateSearchResults(terms);
+    },
+
+    updateSearchResults: function(terms) {
+        let isSubSearch = false;
+
+        if (terms) {
+            isSubSearch = terms.length == this._previousTerms.length;
+            if (isSubSearch) {
+                for (let i = 0; i < terms.length; i++) {
+                    if (terms[i].indexOf(this._previousTerms[i]) != 0) {
+                        isSubSearch = false;
+                        break;
+                    }
                 }
             }
+        } else {
+            terms = this._previousTerms;
         }
 
         let results = [];
         if (isSubSearch) {
-            for (let i = 0; i < this._previousResults.length; i++) {
+            for (let i = 0; i < this._providers.length; i++) {
                 let [provider, previousResults] = this._previousResults[i];
+                provider.tryCancelAsync();
                 try {
                     let providerResults = provider.getSubsearchResultSet(previousResults, terms);
-                    if (providerResults.length > 0)
-                        results.push([provider, providerResults]);
+                    results.push([provider, providerResults]);
                 } catch (error) {
                     global.log ('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
                 }
@@ -383,10 +442,10 @@ SearchSystem.prototype = {
         } else {
             for (let i = 0; i < this._providers.length; i++) {
                 let provider = this._providers[i];
+                provider.tryCancelAsync();
                 try {
                     let providerResults = provider.getInitialResultSet(terms);
-                    if (providerResults.length > 0)
-                        results.push([provider, providerResults]);
+                    results.push([provider, providerResults]);
                 } catch (error) {
                     global.log ('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
                 }
@@ -395,8 +454,7 @@ SearchSystem.prototype = {
 
         this._previousTerms = terms;
         this._previousResults = results;
-
-        return results;
-    }
+        this.emit('results-updated', results);
+    },
 };
 Signals.addSignalMethods(SearchSystem.prototype);
diff --git a/js/ui/searchDisplay.js b/js/ui/searchDisplay.js
index 7e9ba7a..b1a08d9 100644
--- a/js/ui/searchDisplay.js
+++ b/js/ui/searchDisplay.js
@@ -157,6 +157,7 @@ function SearchResults(searchSystem, openSearchSystem) {
 SearchResults.prototype = {
     _init: function(searchSystem, openSearchSystem) {
         this._searchSystem = searchSystem;
+        this._searchSystem.connect('results-updated', Lang.bind(this, this._updateResults));
         this._openSearchSystem = openSearchSystem;
 
         this.actor = new St.BoxLayout({ name: 'searchResults',
@@ -296,15 +297,16 @@ SearchResults.prototype = {
         this._statusText.show();
     },
 
+    doSearch: function (searchString) {
+        this._searchSystem.updateSearch(searchString);
+    },
+
     _metaForProvider: function(provider) {
         return this._providerMeta[this._providers.indexOf(provider)];
     },
 
-    updateSearch: function (searchString) {
-        let results = this._searchSystem.updateSearch(searchString);
-
+    _updateResults: function(searchSystem, results) {
         this._clearDisplay();
-
         if (results.length == 0) {
             this._statusText.set_text(_("No matching results."));
             this._statusText.show();
@@ -314,11 +316,13 @@ SearchResults.prototype = {
             this._statusText.hide();
         }
 
-        let terms = this._searchSystem.getTerms();
+        let terms = searchSystem.getTerms();
         this._openSearchSystem.setSearchTerms(terms);
 
         for (let i = 0; i < results.length; i++) {
             let [provider, providerResults] = results[i];
+            if (providerResults.length == 0)
+                  continue;
             let meta = this._metaForProvider(provider);
             meta.actor.show();
             meta.resultDisplay.renderResults(providerResults, terms);
diff --git a/js/ui/viewSelector.js b/js/ui/viewSelector.js
index 7e5fa27..f569f9e 100644
--- a/js/ui/viewSelector.js
+++ b/js/ui/viewSelector.js
@@ -268,7 +268,7 @@ SearchTab.prototype = {
     _doSearch: function () {
         this._searchTimeoutId = 0;
         let text = this._text.get_text().replace(/^\s+/g, '').replace(/\s+$/g, '');
-        this._searchResults.updateSearch(text);
+        this._searchResults.doSearch(text);
 
         return false;
     }



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