Store: Filter in Matches model.

This commit is contained in:
John Schember 2011-04-20 07:46:27 -04:00
parent f9a931dbfb
commit b415c44cb6

View File

@ -112,6 +112,9 @@ class SearchDialog(QDialog, Ui_Dialog):
query = unicode(self.search_edit.text()) query = unicode(self.search_edit.text())
if not query.strip(): if not query.strip():
return return
# Give the query to the results model so it can do
# futher filtering.
self.results_view.model().set_query(query)
# Plugins are in alphebetic order. Randomize the # Plugins are in alphebetic order. Randomize the
# order of plugin names. This way plugins closer # order of plugin names. This way plugins closer
@ -304,12 +307,11 @@ class SearchThread(Thread):
while self._run and not self.tasks.empty(): while self._run and not self.tasks.empty():
try: try:
query, store_name, store_plugin, timeout = self.tasks.get() query, store_name, store_plugin, timeout = self.tasks.get()
squery = self._clean_query(query) query = self._clean_query(query)
for res in store_plugin.search(squery, timeout=timeout): for res in store_plugin.search(query, timeout=timeout):
if not self._run: if not self._run:
return return
res.store_name = store_name res.store_name = store_name
if SearchFilter(res).parse(query):
self.results.put(res) self.results.put(res)
self.tasks.task_done() self.tasks.task_done()
except: except:
@ -390,7 +392,14 @@ class Matches(QAbstractItemModel):
self.DRM_UNLOCKED_ICON = QPixmap(I('drm-unlocked.png')).scaledToHeight(64) self.DRM_UNLOCKED_ICON = QPixmap(I('drm-unlocked.png')).scaledToHeight(64)
self.DRM_UNKNOWN_ICON = QPixmap(I('dialog_warning.png')).scaledToHeight(64) self.DRM_UNKNOWN_ICON = QPixmap(I('dialog_warning.png')).scaledToHeight(64)
# All matches. Used to determine the order to display
# self.matches because the SearchFilter returns
# matches unordered.
self.all_matches = []
# Only the showing matches.
self.matches = [] self.matches = []
self.query = ''
self.search_filter = SearchFilter()
self.cover_pool = CoverThreadPool(CoverThread, 2) self.cover_pool = CoverThreadPool(CoverThread, 2)
self.cover_pool.start_threads() self.cover_pool.start_threads()
@ -398,15 +407,21 @@ class Matches(QAbstractItemModel):
self.cover_pool.abort() self.cover_pool.abort()
def clear_results(self): def clear_results(self):
self.all_matches = []
self.matches = [] self.matches = []
self.all_matches = []
self.search_filter.clear_search_results()
self.query = ''
self.cover_pool.abort() self.cover_pool.abort()
self.cover_pool.start_threads() self.cover_pool.start_threads()
self.reset() self.reset()
def add_result(self, result): def add_result(self, result):
self.layoutAboutToBeChanged.emit() self.layoutAboutToBeChanged.emit()
self.matches.append(result) self.all_matches.append(result)
self.cover_pool.add_task(result, self.update_result) self.search_filter.add_search_result(result)
self.cover_pool.add_task(result, self.filter_results)
self.filter_results()
self.layoutChanged.emit() self.layoutChanged.emit()
def get_result(self, index): def get_result(self, index):
@ -416,9 +431,17 @@ class Matches(QAbstractItemModel):
else: else:
return None return None
def update_result(self): def filter_results(self):
self.layoutAboutToBeChanged.emit() self.layoutAboutToBeChanged.emit()
self.layoutChanged.emit() if self.query:
self.matches = list(self.search_filter.parse(self.query))
else:
self.matches = list(self.search_filter.universal_set())
self.reorder_matches()
self.layoutAboutToBeChanged.emit()
def set_query(self, query):
self.query = query
def index(self, row, column, parent=QModelIndex()): def index(self, row, column, parent=QModelIndex()):
return self.createIndex(row, column) return self.createIndex(row, column)
@ -497,12 +520,16 @@ class Matches(QAbstractItemModel):
if not self.matches: if not self.matches:
return return
descending = order == Qt.DescendingOrder descending = order == Qt.DescendingOrder
self.matches.sort(None, self.all_matches.sort(None,
lambda x: sort_key(unicode(self.data_as_text(x, col))), lambda x: sort_key(unicode(self.data_as_text(x, col))),
descending) descending)
self.reorder_matches()
if reset: if reset:
self.reset() self.reset()
def reorder_matches(self):
self.matches = sorted(self.matches, key=lambda x: self.all_matches.index(x))
class SearchFilter(SearchQueryParser): class SearchFilter(SearchQueryParser):
@ -517,12 +544,18 @@ class SearchFilter(SearchQueryParser):
'store', 'store',
] ]
def __init__(self, search_result): def __init__(self):
SearchQueryParser.__init__(self, locations=self.USABLE_LOCATIONS) SearchQueryParser.__init__(self, locations=self.USABLE_LOCATIONS)
self.search_result = search_result self.srs = set([])
def add_search_result(self, search_result):
self.srs.add(search_result)
def clear_search_results(self):
self.srs = set([])
def universal_set(self): def universal_set(self):
return set([self.search_result]) return self.srs
def get_matches(self, location, query): def get_matches(self, location, query):
location = location.lower().strip() location = location.lower().strip()
@ -548,33 +581,34 @@ class SearchFilter(SearchQueryParser):
all_locs = set(self.USABLE_LOCATIONS) - set(['all']) all_locs = set(self.USABLE_LOCATIONS) - set(['all'])
locations = all_locs if location == 'all' else [location] locations = all_locs if location == 'all' else [location]
q = { q = {
'author': self.search_result.author.lower(), 'author': lambda x: x.author.lower(),
'cover': self.search_result.cover_url, 'cover': lambda x: x.cover_url,
'drm': self.search_result.drm, 'drm': lambda x: x.drm,
'format': '', 'format': '',
'price': comparable_price(self.search_result.price), 'price': lambda x: comparable_price(x.price),
'store': self.search_result.store_name.lower(), 'store': lambda x: x.store_name.lower(),
'title': self.search_result.title.lower(), 'title': lambda x: x.title.lower(),
} }
for x in ('author', 'format'): for x in ('author', 'format'):
q[x+'s'] = q[x] q[x+'s'] = q[x]
for sr in self.srs:
for locvalue in locations: for locvalue in locations:
ac_val = q[locvalue] accessor = q[locvalue]
if query == 'true': if query == 'true':
if locvalue == 'drm': if locvalue == 'drm':
if ac_val == True: if accessor(sr) == True:
matches.add(self.search_result) matches.add(sr)
else: else:
if ac_val is not None: if accessor(sr) is not None:
matches.add(self.search_result) matches.add(sr)
continue continue
if query == 'false': if query == 'false':
if locvalue == 'drm': if locvalue == 'drm':
if ac_val == False: if accessor(sr) == False:
matches.add(self.search_result) matches.add(sr)
else: else:
if ac_val is None: if accessor(sr) is None:
matches.add(self.search_result) matches.add(sr)
continue continue
# this is bool, so can't match below # this is bool, so can't match below
if locvalue == 'drm': if locvalue == 'drm':
@ -588,9 +622,9 @@ class SearchFilter(SearchQueryParser):
else: else:
m = matchkind m = matchkind
vals = [ac_val] vals = [accessor(sr)]
if _match(query, vals, m): if _match(query, vals, m):
matches.add(self.search_result) matches.add(sr)
break break
except ValueError: # Unicode errors except ValueError: # Unicode errors
traceback.print_exc() traceback.print_exc()