mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Add right-click category search support to the tags browser
This commit is contained in:
parent
03dcd631b4
commit
65e6102e33
@ -186,7 +186,7 @@ class TagsView(QTreeView): # {{{
|
|||||||
self.clear()
|
self.clear()
|
||||||
|
|
||||||
def context_menu_handler(self, action=None, category=None,
|
def context_menu_handler(self, action=None, category=None,
|
||||||
key=None, index=None):
|
key=None, index=None, negate=None):
|
||||||
if not action:
|
if not action:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@ -199,6 +199,9 @@ class TagsView(QTreeView): # {{{
|
|||||||
if action == 'manage_categories':
|
if action == 'manage_categories':
|
||||||
self.user_category_edit.emit(category)
|
self.user_category_edit.emit(category)
|
||||||
return
|
return
|
||||||
|
if action == 'search_category':
|
||||||
|
self.tags_marked.emit(category + ':' + str(not negate))
|
||||||
|
return
|
||||||
if action == 'manage_searches':
|
if action == 'manage_searches':
|
||||||
self.saved_search_edit.emit(category)
|
self.saved_search_edit.emit(category)
|
||||||
return
|
return
|
||||||
@ -268,6 +271,15 @@ class TagsView(QTreeView): # {{{
|
|||||||
m.addAction(col,
|
m.addAction(col,
|
||||||
partial(self.context_menu_handler, action='show', category=col))
|
partial(self.context_menu_handler, action='show', category=col))
|
||||||
|
|
||||||
|
# search by category
|
||||||
|
self.context_menu.addAction(
|
||||||
|
_('Search for books in category %s')%category,
|
||||||
|
partial(self.context_menu_handler, action='search_category',
|
||||||
|
category=key, negate=False))
|
||||||
|
self.context_menu.addAction(
|
||||||
|
_('Search for books not in category %s')%category,
|
||||||
|
partial(self.context_menu_handler, action='search_category',
|
||||||
|
category=key, negate=True))
|
||||||
# Offer specific editors for tags/series/publishers/saved searches
|
# Offer specific editors for tags/series/publishers/saved searches
|
||||||
self.context_menu.addSeparator()
|
self.context_menu.addSeparator()
|
||||||
if key in ['tags', 'publisher', 'series'] or \
|
if key in ['tags', 'publisher', 'series'] or \
|
||||||
|
@ -172,8 +172,9 @@ class ResultCache(SearchQueryParser): # {{{
|
|||||||
'''
|
'''
|
||||||
Stores sorted and filtered metadata in memory.
|
Stores sorted and filtered metadata in memory.
|
||||||
'''
|
'''
|
||||||
def __init__(self, FIELD_MAP, field_metadata):
|
def __init__(self, FIELD_MAP, field_metadata, db_prefs = None):
|
||||||
self.FIELD_MAP = FIELD_MAP
|
self.FIELD_MAP = FIELD_MAP
|
||||||
|
self.db_prefs = db_prefs
|
||||||
self.composites = {}
|
self.composites = {}
|
||||||
for key in field_metadata:
|
for key in field_metadata:
|
||||||
if field_metadata[key]['datatype'] == 'composite':
|
if field_metadata[key]['datatype'] == 'composite':
|
||||||
@ -405,6 +406,22 @@ class ResultCache(SearchQueryParser): # {{{
|
|||||||
matches.add(item[0])
|
matches.add(item[0])
|
||||||
return matches
|
return matches
|
||||||
|
|
||||||
|
def get_user_category_matches(self, location, query, candidates):
|
||||||
|
res = set([])
|
||||||
|
if self.db_prefs is None:
|
||||||
|
return res
|
||||||
|
user_cats = self.db_prefs['user_categories']
|
||||||
|
if location not in user_cats:
|
||||||
|
return res
|
||||||
|
c = set(candidates)
|
||||||
|
for (item, category, ign) in user_cats[location]:
|
||||||
|
s = self.get_matches(category, '=' + item, candidates=c)
|
||||||
|
c -= s
|
||||||
|
res |= s
|
||||||
|
if query == 'false':
|
||||||
|
return candidates - res
|
||||||
|
return res
|
||||||
|
|
||||||
def get_matches(self, location, query, allow_recursion=True, candidates=None):
|
def get_matches(self, location, query, allow_recursion=True, candidates=None):
|
||||||
matches = set([])
|
matches = set([])
|
||||||
if candidates is None:
|
if candidates is None:
|
||||||
@ -443,6 +460,10 @@ class ResultCache(SearchQueryParser): # {{{
|
|||||||
return self.get_numeric_matches(location, query[1:],
|
return self.get_numeric_matches(location, query[1:],
|
||||||
candidates, val_func=vf)
|
candidates, val_func=vf)
|
||||||
|
|
||||||
|
# check for user categories
|
||||||
|
if len(location) >= 2 and location.startswith('@'):
|
||||||
|
return self.get_user_category_matches(location[1:], query.lower(),
|
||||||
|
candidates)
|
||||||
# everything else, or 'all' matches
|
# everything else, or 'all' matches
|
||||||
matchkind = CONTAINS_MATCH
|
matchkind = CONTAINS_MATCH
|
||||||
if (len(query) > 1):
|
if (len(query) > 1):
|
||||||
@ -468,6 +489,8 @@ class ResultCache(SearchQueryParser): # {{{
|
|||||||
for x in range(len(self.FIELD_MAP)):
|
for x in range(len(self.FIELD_MAP)):
|
||||||
col_datatype.append('')
|
col_datatype.append('')
|
||||||
for x in self.field_metadata:
|
for x in self.field_metadata:
|
||||||
|
if x.startswith('@'):
|
||||||
|
continue
|
||||||
if len(self.field_metadata[x]['search_terms']):
|
if len(self.field_metadata[x]['search_terms']):
|
||||||
db_col[x] = self.field_metadata[x]['rec_index']
|
db_col[x] = self.field_metadata[x]['rec_index']
|
||||||
if self.field_metadata[x]['datatype'] not in \
|
if self.field_metadata[x]['datatype'] not in \
|
||||||
|
@ -332,7 +332,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
self.book_on_device_func = None
|
self.book_on_device_func = None
|
||||||
self.data = ResultCache(self.FIELD_MAP, self.field_metadata)
|
self.data = ResultCache(self.FIELD_MAP, self.field_metadata, db_prefs=self.prefs)
|
||||||
self.search = self.data.search
|
self.search = self.data.search
|
||||||
self.search_getting_ids = self.data.search_getting_ids
|
self.search_getting_ids = self.data.search_getting_ids
|
||||||
self.refresh = functools.partial(self.data.refresh, self)
|
self.refresh = functools.partial(self.data.refresh, self)
|
||||||
|
@ -475,6 +475,8 @@ class FieldMetadata(dict):
|
|||||||
val = self._tb_cats[key]
|
val = self._tb_cats[key]
|
||||||
if val['is_category'] and val['kind'] in ('user', 'search'):
|
if val['is_category'] and val['kind'] in ('user', 'search'):
|
||||||
del self._tb_cats[key]
|
del self._tb_cats[key]
|
||||||
|
if key in self._search_term_map:
|
||||||
|
del self._search_term_map[key]
|
||||||
|
|
||||||
def cc_series_index_column_for(self, key):
|
def cc_series_index_column_for(self, key):
|
||||||
return self._tb_cats[key]['rec_index'] + 1
|
return self._tb_cats[key]['rec_index'] + 1
|
||||||
@ -482,11 +484,12 @@ class FieldMetadata(dict):
|
|||||||
def add_user_category(self, label, name):
|
def add_user_category(self, label, name):
|
||||||
if label in self._tb_cats:
|
if label in self._tb_cats:
|
||||||
raise ValueError('Duplicate user field [%s]'%(label))
|
raise ValueError('Duplicate user field [%s]'%(label))
|
||||||
self._tb_cats[label] = {'table':None, 'column':None,
|
self._tb_cats[label] = {'table':None, 'column':None,
|
||||||
'datatype':None, 'is_multiple':None,
|
'datatype':None, 'is_multiple':None,
|
||||||
'kind':'user', 'name':name,
|
'kind':'user', 'name':name,
|
||||||
'search_terms':[], 'is_custom':False,
|
'search_terms':[label],'is_custom':False,
|
||||||
'is_category':True}
|
'is_category':True}
|
||||||
|
self._add_search_terms_to_map(label, [label])
|
||||||
|
|
||||||
def add_search_category(self, label, name):
|
def add_search_category(self, label, name):
|
||||||
if label in self._tb_cats:
|
if label in self._tb_cats:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user