From 85dae56a31e974301ece03062b4f57835c4f620f Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 10 Feb 2009 14:12:13 -0500 Subject: [PATCH] Bug 571203 - Handle spaces in overlay search Previously we were stripping all whitespace. Instead, just strip leading+trailing whitespace, split the remaining search into individual terms which we search for independently. Items are grouped by the number of terms they match, then sorted alphabetically. --- js/ui/appDisplay.js | 16 ++++++------ js/ui/docDisplay.js | 35 +++++++++++++------------- js/ui/genericDisplay.js | 54 ++++++++++++++++++++++++++++++++--------- js/ui/overlay.js | 3 ++- 4 files changed, 68 insertions(+), 40 deletions(-) diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js index c8befb809..ec1be56fa 100644 --- a/js/ui/appDisplay.js +++ b/js/ui/appDisplay.js @@ -178,15 +178,13 @@ AppDisplay.prototype = { } }, - // Sorts the list of item ids in-place based on the alphabetical order of the names of - // the items associated with the ids. - _sortItems : function(itemIds) { - let me = this; - itemIds.sort(function (a,b) { - let appA = me._allItems[a]; - let appB = me._allItems[b]; - return appA.get_name().localeCompare(appB.get_name()); - }); + // Compares items associated with the item ids based on the alphabetical order + // of the item names. + // Returns an integer value indicating the result of the comparison. + _compareItems : function(itemIdA, itemIdB) { + let appA = this._allItems[itemIdA]; + let appB = this._allItems[itemIdB]; + return appA.get_name().localeCompare(appB.get_name()); }, // Checks if the item info can be a match for the search string by checking diff --git a/js/ui/docDisplay.js b/js/ui/docDisplay.js index ade5d0550..4b2f58c9f 100644 --- a/js/ui/docDisplay.js +++ b/js/ui/docDisplay.js @@ -3,6 +3,7 @@ const Clutter = imports.gi.Clutter; const Gio = imports.gi.Gio; const Gtk = imports.gi.Gtk; +const Lang = imports.lang; const Shell = imports.gi.Shell; const Signals = imports.signals; @@ -153,7 +154,7 @@ DocDisplay.prototype = { for (docId in this._allItems) { docIds.push(docId); } - this._sortItems(docIds); + docIds.sort(Lang.bind(this, function (a,b) { return this._compareItems(a,b); })); let added = 0; for (let i = 0; i < docIds.length && added < this._maxItems; i++) { @@ -166,23 +167,21 @@ DocDisplay.prototype = { } }, - // Sorts the list of item ids in-place based on how recently the items associated with - // the ids were last visited. - _sortItems : function(itemIds) { - let me = this; - itemIds.sort(function (a,b) { - let docA = me._allItems[a]; - let docB = me._allItems[b]; - // We actually used get_modified() instead of get_visited() here, as GtkRecentInfo - // doesn't updated get_visited() correctly. - // See http://bugzilla.gnome.org/show_bug.cgi?id=567094 - if (docA.get_modified() > docB.get_modified()) - return -1; - else if (docA.get_modified() < docB.get_modified()) - return 1; - else - return 0; - }); + // Compares items associated with the item ids based on how recently the items + // were last visited. + // Returns an integer value indicating the result of the comparison. + _compareItems : function(itemIdA, itemIdB) { + let docA = this._allItems[itemIdA]; + let docB = this._allItems[itemIdB]; + // We actually used get_modified() instead of get_visited() here, as GtkRecentInfo + // doesn't updated get_visited() correctly. + // See http://bugzilla.gnome.org/show_bug.cgi?id=567094 + if (docA.get_modified() > docB.get_modified()) + return -1; + else if (docA.get_modified() < docB.get_modified()) + return 1; + else + return 0; }, // Checks if the item info can be a match for the search string by checking diff --git a/js/ui/genericDisplay.js b/js/ui/genericDisplay.js index 1f4064f9b..f2c52b1ab 100644 --- a/js/ui/genericDisplay.js +++ b/js/ui/genericDisplay.js @@ -6,8 +6,8 @@ const Gio = imports.gi.Gio; const Gtk = imports.gi.Gtk; const Lang = imports.lang; const Pango = imports.gi.Pango; -const Shell = imports.gi.Shell; const Signals = imports.signals; +const Shell = imports.gi.Shell; const Tidy = imports.gi.Tidy; const DND = imports.ui.dnd; @@ -391,9 +391,11 @@ GenericDisplay.prototype = { throw new Error("Not implemented"); }, - // Sorts the list of item ids in-place based on the order in which the items - // associated with the ids should be displayed. - _sortItems: function(itemIds) { + // Compares items associated with the item ids based on the order in which the + // items should be displayed. + // Intended to be used as a compareFunction for array.sort(). + // Returns an integer value indicating the result of the comparison. + _compareItems: function(itemIdA, itemIdB) { throw new Error("Not implemented"); }, @@ -424,15 +426,43 @@ GenericDisplay.prototype = { // and displays up to this._maxItems that matched. _doSearchFilter: function() { this._removeAllDisplayItems(); - let matchedItems = []; - for (itemId in this._allItems) { - let item = this._allItems[itemId]; - if (this._isInfoMatching(item, this._search)) - matchedItems.push(itemId); + let matchedItems = {}; + + // Break the search up into terms, and search for each + // individual term. Keep track of the number of terms + // each item matched. + let terms = this._search.split(/\s+/); + for (let i = 0; i < terms.length; i++) { + let term = terms[i]; + for (itemId in this._allItems) { + let item = this._allItems[itemId]; + if (this._isInfoMatching(item, term)) { + let count = matchedItems[itemId]; + if (!count) + count = 0; + count += 1; + matchedItems[itemId] = count; + } + } } - this._sortItems(matchedItems); - for (let i = 0; i < matchedItems.length && i < this._maxItems; i++) { - this._addDisplayItem(matchedItems[i]); + + let matchedList = []; + for (itemId in matchedItems) { + matchedList.push(itemId); + } + matchedList.sort(Lang.bind(this, function (a, b) { + let countA = matchedItems[a]; + let countB = matchedItems[b]; + if (countA > countB) + return -1; + else if (countA < countB) + return 1; + else + return this._compareItems(a, b); + })); + + for (var i = 0; i < matchedList.length && i < this._maxItems; i++) { + this._addDisplayItem(matchedList[i]); } }, diff --git a/js/ui/overlay.js b/js/ui/overlay.js index 088f065b5..81de87b39 100644 --- a/js/ui/overlay.js +++ b/js/ui/overlay.js @@ -119,7 +119,8 @@ Sideshow.prototype = { if (me._searchQueued) return; Mainloop.timeout_add(250, function() { - let text = me._searchEntry.text.replace(/\s/g, ""); + // Strip leading and trailing whitespace + let text = me._searchEntry.text.replace(/^\s+/g, "").replace(/\s+$/g, ""); me._searchQueued = false; me._searchActive = text != ''; me._appDisplay.setSearch(text);