mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
1) Add tweak to make user-defined search terms for searching across multiple fields.
2) Make parse exceptions visible as the tooltip in the GUI
This commit is contained in:
parent
652238538e
commit
7fa99ffb57
@ -96,3 +96,17 @@ auto_connect_to_folder = ''
|
|||||||
# Specify a tag to be automatically applied when a book is added to the library.
|
# Specify a tag to be automatically applied when a book is added to the library.
|
||||||
# Example: add_tag_to_new_books='ToDo'
|
# Example: add_tag_to_new_books='ToDo'
|
||||||
add_tag_to_new_books = ''
|
add_tag_to_new_books = ''
|
||||||
|
|
||||||
|
|
||||||
|
# Create search terms to apply a query across several built-in search terms.
|
||||||
|
# Syntax: {'new term':['existing term 1', 'term 2', ...], 'new':['old'...] ...}
|
||||||
|
# Example: create the term 'myseries' that when used as myseries:foo would
|
||||||
|
# search all of the search categories 'series', '#myseries', and '#myseries2':
|
||||||
|
# grouped_search_terms={'myseries':['series','#myseries', '#myseries2']}
|
||||||
|
# Example: two search terms 'a' and 'b' both that search 'tags' and '#mytags':
|
||||||
|
# grouped_search_terms={'a':['tags','#mytags'], 'b':['tags','#mytags']}
|
||||||
|
# Note: You cannot create a search term that is a duplicate of an existing term.
|
||||||
|
# Such duplicates will be silently ignored. Also note that search terms ignore
|
||||||
|
# case. 'MySearch' and 'mysearch' are the same term.
|
||||||
|
grouped_search_terms = {}
|
||||||
|
|
||||||
|
@ -236,8 +236,8 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
def search(self, text, reset=True):
|
def search(self, text, reset=True):
|
||||||
try:
|
try:
|
||||||
self.db.search(text)
|
self.db.search(text)
|
||||||
except ParseException:
|
except ParseException as e:
|
||||||
self.searched.emit(False)
|
self.searched.emit(e.msg)
|
||||||
return
|
return
|
||||||
self.last_search = text
|
self.last_search = text
|
||||||
if reset:
|
if reset:
|
||||||
|
@ -90,6 +90,7 @@ class SearchBox2(QComboBox):
|
|||||||
self.setSizeAdjustPolicy(self.AdjustToMinimumContentsLengthWithIcon)
|
self.setSizeAdjustPolicy(self.AdjustToMinimumContentsLengthWithIcon)
|
||||||
self.setMinimumContentsLength(25)
|
self.setMinimumContentsLength(25)
|
||||||
self._in_a_search = False
|
self._in_a_search = False
|
||||||
|
self.tool_tip_text = self.toolTip()
|
||||||
|
|
||||||
def initialize(self, opt_name, colorize=False, help_text=_('Search')):
|
def initialize(self, opt_name, colorize=False, help_text=_('Search')):
|
||||||
self.as_you_type = config['search_as_you_type']
|
self.as_you_type = config['search_as_you_type']
|
||||||
@ -100,6 +101,7 @@ class SearchBox2(QComboBox):
|
|||||||
self.clear_to_help()
|
self.clear_to_help()
|
||||||
|
|
||||||
def normalize_state(self):
|
def normalize_state(self):
|
||||||
|
self.setToolTip(self.tool_tip_text)
|
||||||
if self.help_state:
|
if self.help_state:
|
||||||
self.setEditText('')
|
self.setEditText('')
|
||||||
self.line_edit.setStyleSheet(
|
self.line_edit.setStyleSheet(
|
||||||
@ -112,6 +114,7 @@ class SearchBox2(QComboBox):
|
|||||||
self.normal_background)
|
self.normal_background)
|
||||||
|
|
||||||
def clear_to_help(self):
|
def clear_to_help(self):
|
||||||
|
self.setToolTip(self.tool_tip_text)
|
||||||
if self.help_state:
|
if self.help_state:
|
||||||
return
|
return
|
||||||
self.help_state = True
|
self.help_state = True
|
||||||
@ -131,6 +134,9 @@ class SearchBox2(QComboBox):
|
|||||||
self.clear_to_help()
|
self.clear_to_help()
|
||||||
|
|
||||||
def search_done(self, ok):
|
def search_done(self, ok):
|
||||||
|
if isinstance(ok, basestring):
|
||||||
|
self.setToolTip(ok)
|
||||||
|
ok = False
|
||||||
if not unicode(self.currentText()).strip():
|
if not unicode(self.currentText()).strip():
|
||||||
return self.clear_to_help()
|
return self.clear_to_help()
|
||||||
self._in_a_search = ok
|
self._in_a_search = ok
|
||||||
|
@ -319,12 +319,18 @@ class ResultCache(SearchQueryParser):
|
|||||||
matches.add(item[0])
|
matches.add(item[0])
|
||||||
return matches
|
return matches
|
||||||
|
|
||||||
def get_matches(self, location, query):
|
def get_matches(self, location, query, allow_recursion=True):
|
||||||
matches = set([])
|
matches = set([])
|
||||||
if query and query.strip():
|
if query and query.strip():
|
||||||
# get metadata key associated with the search term. Eliminates
|
# get metadata key associated with the search term. Eliminates
|
||||||
# dealing with plurals and other aliases
|
# dealing with plurals and other aliases
|
||||||
location = self.field_metadata.search_term_to_key(location.lower().strip())
|
location = self.field_metadata.search_term_to_key(location.lower().strip())
|
||||||
|
if isinstance(location, list):
|
||||||
|
if allow_recursion:
|
||||||
|
for loc in location:
|
||||||
|
matches |= self.get_matches(loc, query, allow_recursion=False)
|
||||||
|
return matches
|
||||||
|
raise ParseException(query, len(query), 'Recursive query group detected', self)
|
||||||
|
|
||||||
# take care of dates special case
|
# take care of dates special case
|
||||||
if location in self.field_metadata and \
|
if location in self.field_metadata and \
|
||||||
|
@ -297,6 +297,13 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
if len(saved_searches().names()):
|
if len(saved_searches().names()):
|
||||||
tb_cats.add_search_category(label='search', name=_('Searches'))
|
tb_cats.add_search_category(label='search', name=_('Searches'))
|
||||||
|
|
||||||
|
gst = tweaks['grouped_search_terms']
|
||||||
|
for t in gst:
|
||||||
|
try:
|
||||||
|
self.field_metadata._add_search_terms_to_map(gst[t], [t])
|
||||||
|
except ValueError:
|
||||||
|
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)
|
||||||
self.search = self.data.search
|
self.search = self.data.search
|
||||||
|
@ -475,9 +475,7 @@ class FieldMetadata(dict):
|
|||||||
# ])
|
# ])
|
||||||
|
|
||||||
def get_search_terms(self):
|
def get_search_terms(self):
|
||||||
s_keys = []
|
s_keys = sorted(self._search_term_map.keys())
|
||||||
for v in self._tb_cats.itervalues():
|
|
||||||
map((lambda x:s_keys.append(x)), v['search_terms'])
|
|
||||||
for v in self.search_items:
|
for v in self.search_items:
|
||||||
s_keys.append(v)
|
s_keys.append(v)
|
||||||
# if set(s_keys) != self.DEFAULT_LOCATIONS:
|
# if set(s_keys) != self.DEFAULT_LOCATIONS:
|
||||||
@ -488,6 +486,9 @@ class FieldMetadata(dict):
|
|||||||
def _add_search_terms_to_map(self, key, terms):
|
def _add_search_terms_to_map(self, key, terms):
|
||||||
if terms is not None:
|
if terms is not None:
|
||||||
for t in terms:
|
for t in terms:
|
||||||
|
t = t.lower()
|
||||||
|
if t in self._search_term_map:
|
||||||
|
raise ValueError('Attempt to add duplicate search term "%s"'%t)
|
||||||
self._search_term_map[t] = key
|
self._search_term_map[t] = key
|
||||||
|
|
||||||
def search_term_to_key(self, term):
|
def search_term_to_key(self, term):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user