mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Tag Browser: Fix incorrect grouping of words starting with graphemes, such as ash. Fixes #1422116 [Some letters break the category splitting](https://bugs.launchpad.net/calibre/+bug/1422116)
Fix Virtual Libraries not working in the View Manager plugin if the user never clicks the Virtual Library button before using the plugin. Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
commit
69b15134df
@ -941,11 +941,13 @@ class Cache(object):
|
|||||||
return self._search_api(self, query, restriction, virtual_fields=virtual_fields, book_ids=book_ids)
|
return self._search_api(self, query, restriction, virtual_fields=virtual_fields, book_ids=book_ids)
|
||||||
|
|
||||||
@api
|
@api
|
||||||
def get_categories(self, sort='name', book_ids=None, icon_map=None, already_fixed=None):
|
def get_categories(self, sort='name', book_ids=None, icon_map=None, already_fixed=None,
|
||||||
|
first_letter_sort=False):
|
||||||
' Used internally to implement the Tag Browser '
|
' Used internally to implement the Tag Browser '
|
||||||
try:
|
try:
|
||||||
with self.safe_read_lock:
|
with self.safe_read_lock:
|
||||||
return get_categories(self, sort=sort, book_ids=book_ids, icon_map=icon_map)
|
return get_categories(self, sort=sort, book_ids=book_ids, icon_map=icon_map,
|
||||||
|
first_letter_sort=first_letter_sort)
|
||||||
except InvalidLinkTable as err:
|
except InvalidLinkTable as err:
|
||||||
bad_field = err.field_name
|
bad_field = err.field_name
|
||||||
if bad_field == already_fixed:
|
if bad_field == already_fixed:
|
||||||
|
@ -15,7 +15,7 @@ from future_builtins import map
|
|||||||
from calibre.ebooks.metadata import author_to_author_sort
|
from calibre.ebooks.metadata import author_to_author_sort
|
||||||
from calibre.library.field_metadata import TagsIcons
|
from calibre.library.field_metadata import TagsIcons
|
||||||
from calibre.utils.config_base import tweaks
|
from calibre.utils.config_base import tweaks
|
||||||
from calibre.utils.icu import sort_key
|
from calibre.utils.icu import sort_key, collation_order
|
||||||
|
|
||||||
CATEGORY_SORTS = ('name', 'popularity', 'rating') # This has to be a tuple not a set
|
CATEGORY_SORTS = ('name', 'popularity', 'rating') # This has to be a tuple not a set
|
||||||
|
|
||||||
@ -116,19 +116,22 @@ def clean_user_categories(dbcache):
|
|||||||
pass
|
pass
|
||||||
return new_cats
|
return new_cats
|
||||||
|
|
||||||
def sort_categories(items, sort):
|
def sort_categories(items, sort, first_letter_sort=False):
|
||||||
reverse = True
|
|
||||||
if sort == 'popularity':
|
if sort == 'popularity':
|
||||||
key=attrgetter('count')
|
key=lambda x:(-getattr(x, 'count', 0), sort_key(x.sort or x.name))
|
||||||
elif sort == 'rating':
|
elif sort == 'rating':
|
||||||
key=attrgetter('avg_rating')
|
key=lambda x:(-getattr(x, 'avg_rating', 0.0), sort_key(x.sort or x.name))
|
||||||
else:
|
else:
|
||||||
key=lambda x:sort_key(x.sort or x.name)
|
if first_letter_sort:
|
||||||
reverse=False
|
key=lambda x:(collation_order(icu_upper(x.sort or x.name or ' ')),
|
||||||
items.sort(key=key, reverse=reverse)
|
sort_key(x.sort or x.name))
|
||||||
|
else:
|
||||||
|
key=lambda x:sort_key(x.sort or x.name)
|
||||||
|
items.sort(key=key)
|
||||||
return items
|
return items
|
||||||
|
|
||||||
def get_categories(dbcache, sort='name', book_ids=None, icon_map=None):
|
def get_categories(dbcache, sort='name', book_ids=None, icon_map=None,
|
||||||
|
first_letter_sort=False):
|
||||||
if icon_map is not None and type(icon_map) != TagsIcons:
|
if icon_map is not None and type(icon_map) != TagsIcons:
|
||||||
raise TypeError('icon_map passed to get_categories must be of type TagIcons')
|
raise TypeError('icon_map passed to get_categories must be of type TagIcons')
|
||||||
if sort not in CATEGORY_SORTS:
|
if sort not in CATEGORY_SORTS:
|
||||||
@ -170,7 +173,7 @@ def get_categories(dbcache, sort='name', book_ids=None, icon_map=None):
|
|||||||
cat['is_multiple'] and cat['display'].get('is_names', False)):
|
cat['is_multiple'] and cat['display'].get('is_names', False)):
|
||||||
for item in cats:
|
for item in cats:
|
||||||
item.sort = author_to_author_sort(item.sort)
|
item.sort = author_to_author_sort(item.sort)
|
||||||
sort_categories(cats, sort)
|
sort_categories(cats, sort, first_letter_sort=first_letter_sort)
|
||||||
categories[category] = cats
|
categories[category] = cats
|
||||||
|
|
||||||
# Needed for legacy databases that have multiple ratings that
|
# Needed for legacy databases that have multiple ratings that
|
||||||
|
@ -341,6 +341,7 @@ class SearchRestrictionMixin(object):
|
|||||||
self.ar_menu = QMenu(_('Additional restriction'))
|
self.ar_menu = QMenu(_('Additional restriction'))
|
||||||
self.edit_menu = QMenu(_('Edit Virtual Library'))
|
self.edit_menu = QMenu(_('Edit Virtual Library'))
|
||||||
self.rm_menu = QMenu(_('Remove Virtual Library'))
|
self.rm_menu = QMenu(_('Remove Virtual Library'))
|
||||||
|
self.search_restriction_list_built = False
|
||||||
|
|
||||||
def add_virtual_library(self, db, name, search):
|
def add_virtual_library(self, db, name, search):
|
||||||
virt_libs = db.prefs.get('virtual_libraries', {})
|
virt_libs = db.prefs.get('virtual_libraries', {})
|
||||||
@ -498,6 +499,7 @@ class SearchRestrictionMixin(object):
|
|||||||
return name[0:MAX_VIRTUAL_LIBRARY_NAME_LENGTH].strip()
|
return name[0:MAX_VIRTUAL_LIBRARY_NAME_LENGTH].strip()
|
||||||
|
|
||||||
def build_search_restriction_list(self):
|
def build_search_restriction_list(self):
|
||||||
|
self.search_restriction_list_built = True
|
||||||
from calibre.gui2.ui import get_gui
|
from calibre.gui2.ui import get_gui
|
||||||
m = self.ar_menu
|
m = self.ar_menu
|
||||||
m.clear()
|
m.clear()
|
||||||
@ -539,6 +541,8 @@ class SearchRestrictionMixin(object):
|
|||||||
self.apply_search_restriction(index)
|
self.apply_search_restriction(index)
|
||||||
|
|
||||||
def apply_named_search_restriction(self, name):
|
def apply_named_search_restriction(self, name):
|
||||||
|
if not self.search_restriction_list_built:
|
||||||
|
self.build_search_restriction_list()
|
||||||
if not name:
|
if not name:
|
||||||
r = 0
|
r = 0
|
||||||
else:
|
else:
|
||||||
@ -549,6 +553,8 @@ class SearchRestrictionMixin(object):
|
|||||||
self.apply_search_restriction(r)
|
self.apply_search_restriction(r)
|
||||||
|
|
||||||
def apply_text_search_restriction(self, search):
|
def apply_text_search_restriction(self, search):
|
||||||
|
if not self.search_restriction_list_built:
|
||||||
|
self.build_search_restriction_list()
|
||||||
search = unicode(search)
|
search = unicode(search)
|
||||||
if not search:
|
if not search:
|
||||||
self.search_restriction.setCurrentIndex(0)
|
self.search_restriction.setCurrentIndex(0)
|
||||||
@ -567,6 +573,8 @@ class SearchRestrictionMixin(object):
|
|||||||
self._apply_search_restriction(search, self._trim_restriction_name(s))
|
self._apply_search_restriction(search, self._trim_restriction_name(s))
|
||||||
|
|
||||||
def apply_search_restriction(self, i):
|
def apply_search_restriction(self, i):
|
||||||
|
if not self.search_restriction_list_built:
|
||||||
|
self.build_search_restriction_list()
|
||||||
if i == 1:
|
if i == 1:
|
||||||
self.apply_text_search_restriction(unicode(self.search.currentText()))
|
self.apply_text_search_restriction(unicode(self.search.currentText()))
|
||||||
elif i == 2 and unicode(self.search_restriction.currentText()).startswith('*'):
|
elif i == 2 and unicode(self.search_restriction.currentText()).startswith('*'):
|
||||||
|
@ -865,16 +865,19 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
# Get the categories
|
# Get the categories
|
||||||
if self.db.data.get_base_restriction() or self.db.data.get_search_restriction():
|
if self.db.data.get_base_restriction() or self.db.data.get_search_restriction():
|
||||||
try:
|
try:
|
||||||
data = self.db.get_categories(sort=sort,
|
data = self.db.new_api.get_categories(sort=sort,
|
||||||
icon_map=self.category_icon_map,
|
icon_map=self.category_icon_map,
|
||||||
ids=self.db.search('', return_matches=True, sort_results=False))
|
book_ids=self.db.search('', return_matches=True, sort_results=False),
|
||||||
|
first_letter_sort = self.collapse_model == 'first letter')
|
||||||
except:
|
except:
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
data = self.db.get_categories(sort=sort, icon_map=self.category_icon_map)
|
data = self.db.new_api.get_categories(sort=sort, icon_map=self.category_icon_map,
|
||||||
|
first_letter_sort = self.collapse_model == 'first letter')
|
||||||
self.restriction_error.emit()
|
self.restriction_error.emit()
|
||||||
else:
|
else:
|
||||||
data = self.db.get_categories(sort=sort, icon_map=self.category_icon_map)
|
data = self.db.new_api.get_categories(sort=sort, icon_map=self.category_icon_map,
|
||||||
|
first_letter_sort = self.collapse_model == 'first letter')
|
||||||
|
|
||||||
# Reconstruct the user categories, putting them into metadata
|
# Reconstruct the user categories, putting them into metadata
|
||||||
self.db.field_metadata.remove_dynamic_categories()
|
self.db.field_metadata.remove_dynamic_categories()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user