Optimize subsearches
This is probably not the biggest optimization that needs to be made at least for application searching, but we can optimize the case where we're going from a search of "fi" to "fire" by just re-searching the list of things we already had that matched "fi" instead of looping over everything. https://bugzilla.gnome.org/show_bug.cgi?id=596119
This commit is contained in:
parent
3564d78d30
commit
32ef951fe0
@ -17,6 +17,10 @@ const DND = imports.ui.dnd;
|
|||||||
const Link = imports.ui.link;
|
const Link = imports.ui.link;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
|
const RedisplayFlags = { NONE: 0,
|
||||||
|
RESET_CONTROLS: 1 << 0,
|
||||||
|
SUBSEARCH: 1 << 1 };
|
||||||
|
|
||||||
const ITEM_DISPLAY_NAME_COLOR = new Clutter.Color();
|
const ITEM_DISPLAY_NAME_COLOR = new Clutter.Color();
|
||||||
ITEM_DISPLAY_NAME_COLOR.from_pixel(0xffffffff);
|
ITEM_DISPLAY_NAME_COLOR.from_pixel(0xffffffff);
|
||||||
const ITEM_DISPLAY_DESCRIPTION_COLOR = new Clutter.Color();
|
const ITEM_DISPLAY_DESCRIPTION_COLOR = new Clutter.Color();
|
||||||
@ -357,8 +361,14 @@ GenericDisplay.prototype = {
|
|||||||
|
|
||||||
// Sets the search string and displays the matching items.
|
// Sets the search string and displays the matching items.
|
||||||
setSearch: function(text) {
|
setSearch: function(text) {
|
||||||
this._search = text.toLowerCase();
|
let lowertext = text.toLowerCase();
|
||||||
this._redisplay(true);
|
let flags = RedisplayFlags.RESET_CONTROLS;
|
||||||
|
if (this._search != '') {
|
||||||
|
if (lowertext.indexOf(this._search) == 0)
|
||||||
|
flags |= RedisplayFlags.SUBSEARCH;
|
||||||
|
}
|
||||||
|
this._search = lowertext;
|
||||||
|
this._redisplay(flags);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Launches the item that is currently selected, closing the Overview
|
// Launches the item that is currently selected, closing the Overview
|
||||||
@ -439,7 +449,7 @@ GenericDisplay.prototype = {
|
|||||||
|
|
||||||
// Load the initial state
|
// Load the initial state
|
||||||
load: function() {
|
load: function() {
|
||||||
this._redisplay(true);
|
this._redisplay(RedisplayFlags.RESET_CONTROLS);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Should be called when the display is closed
|
// Should be called when the display is closed
|
||||||
@ -587,19 +597,23 @@ GenericDisplay.prototype = {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Updates the displayed items, applying the search string if one exists.
|
* Updates the displayed items, applying the search string if one exists.
|
||||||
*
|
* @flags: Flags controlling redisplay behavior as follows:
|
||||||
* resetPage - indicates if the page selection should be reset when displaying the matching results.
|
* RESET_CONTROLS - indicates if the page selection should be reset when displaying the matching results.
|
||||||
* We reset the page selection when the change in results was initiated by the user by
|
* We reset the page selection when the change in results was initiated by the user by
|
||||||
* entering a different search criteria or by viewing the results list in a different
|
* entering a different search criteria or by viewing the results list in a different
|
||||||
* size mode, but we keep the page selection the same if the results got updated on
|
* size mode, but we keep the page selection the same if the results got updated on
|
||||||
* their own while the user was browsing through the result pages.
|
* their own while the user was browsing through the result pages.
|
||||||
|
* SUBSEARCH - Indicates that the current _search is a superstring of the previous
|
||||||
|
* one, which implies we only need to re-search through previous results.
|
||||||
*/
|
*/
|
||||||
_redisplay: function(resetPage) {
|
_redisplay: function(flags) {
|
||||||
|
let resetPage = flags & RedisplayFlags.RESET_CONTROLS;
|
||||||
|
let isSubSearch = flags & RedisplayFlags.SUBSEARCH;
|
||||||
this._refreshCache();
|
this._refreshCache();
|
||||||
if (!this._filterActive())
|
if (!this._filterActive())
|
||||||
this._setDefaultList();
|
this._setDefaultList();
|
||||||
else
|
else
|
||||||
this._doSearchFilter();
|
this._doSearchFilter(isSubSearch);
|
||||||
|
|
||||||
if (resetPage)
|
if (resetPage)
|
||||||
this._list.page = 0;
|
this._list.page = 0;
|
||||||
@ -643,35 +657,49 @@ GenericDisplay.prototype = {
|
|||||||
|
|
||||||
//// Private methods ////
|
//// Private methods ////
|
||||||
|
|
||||||
_getSearchMatchedItems: function() {
|
_getItemSearchScore: function(itemId, terms) {
|
||||||
let matchedItemsForSearch = {};
|
let item = this._allItems[itemId];
|
||||||
|
let score = 0;
|
||||||
|
for (let i = 0; i < terms.length; i++) {
|
||||||
|
let term = terms[i];
|
||||||
|
if (this._isInfoMatching(item, term)) {
|
||||||
|
score++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return score;
|
||||||
|
},
|
||||||
|
|
||||||
|
_getSearchMatchedItems: function(isSubSearch) {
|
||||||
// Break the search up into terms, and search for each
|
// Break the search up into terms, and search for each
|
||||||
// individual term. Keep track of the number of terms
|
// individual term. Keep track of the number of terms
|
||||||
// each item matched.
|
// each item matched.
|
||||||
let terms = this._search.split(/\s+/);
|
let terms = this._search.split(/\s+/);
|
||||||
for (let i = 0; i < terms.length; i++) {
|
let matchScores = {};
|
||||||
let term = terms[i];
|
|
||||||
for (itemId in this._allItems) {
|
if (isSubSearch) {
|
||||||
let item = this._allItems[itemId];
|
for (let i = 0; i < this._matchedItems.length; i++) {
|
||||||
if (this._isInfoMatching(item, term)) {
|
let itemId = this._matchedItems[i];
|
||||||
let count = matchedItemsForSearch[itemId];
|
let score = this._getItemSearchScore(itemId, terms);
|
||||||
if (!count)
|
if (score > 0)
|
||||||
count = 0;
|
matchScores[itemId] = score;
|
||||||
count += 1;
|
}
|
||||||
matchedItemsForSearch[itemId] = count;
|
} else {
|
||||||
|
for (let itemId in this._allItems) {
|
||||||
|
let score = this._getItemSearchScore(itemId, terms);
|
||||||
|
if (score > 0)
|
||||||
|
matchScores[itemId] = score;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return matchScores;
|
||||||
return matchedItemsForSearch;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Applies the search string to the list of items to find matches,
|
// Applies the search string to the list of items to find matches,
|
||||||
// and displays the matching items.
|
// and displays the matching items.
|
||||||
_doSearchFilter: function() {
|
_doSearchFilter: function(isSubSearch) {
|
||||||
let matchedItemsForSearch;
|
let matchedItemsForSearch;
|
||||||
|
|
||||||
if (this._filterActive()) {
|
if (this._filterActive()) {
|
||||||
matchedItemsForSearch = this._getSearchMatchedItems();
|
matchedItemsForSearch = this._getSearchMatchedItems(isSubSearch);
|
||||||
} else {
|
} else {
|
||||||
matchedItemsForSearch = {};
|
matchedItemsForSearch = {};
|
||||||
for (let itemId in this._allItems) {
|
for (let itemId in this._allItems) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user