mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 02:34:06 -04:00
Fix sort order of similarly-named hierarchical categories.
See https://www.mobileread.com/forums/showthread.php?t=356598
This commit is contained in:
parent
fb3d163796
commit
a25d08e268
@ -146,8 +146,23 @@ def category_display_order(ordered_cats, all_cats):
|
|||||||
numeric_collation = prefs['numeric_collation']
|
numeric_collation = prefs['numeric_collation']
|
||||||
|
|
||||||
|
|
||||||
def sort_key_for_name_and_first_letter(x):
|
def sort_key_for_popularity(x, hierarchical_categories=None):
|
||||||
|
return (-getattr(x, 'count', 0), sort_key(x.sort or x.name))
|
||||||
|
|
||||||
|
|
||||||
|
def sort_key_for_rating(x, hierarchical_categories=None):
|
||||||
|
return (-getattr(x, 'avg_rating', 0.0), sort_key(x.sort or x.name))
|
||||||
|
|
||||||
|
|
||||||
|
# When sorting by name, treat the period in hierarchical categories as a tab so
|
||||||
|
# that the value sorts above similarly-named items. Example: "foo.bar" should
|
||||||
|
# sort above "foo a.bar". Without this substitution "foo.bar" sorts below "foo
|
||||||
|
# a.bar" because '.' sorts higher than space.
|
||||||
|
|
||||||
|
def sort_key_for_name_and_first_letter(x, hierarchical_categories={}):
|
||||||
v1 = icu_upper(x.sort or x.name)
|
v1 = icu_upper(x.sort or x.name)
|
||||||
|
if x.category in hierarchical_categories:
|
||||||
|
v1 = v1.replace('.', '\t')
|
||||||
v2 = v1 or ' '
|
v2 = v1 or ' '
|
||||||
# The idea is that '9999999999' is larger than any digit so all digits
|
# The idea is that '9999999999' is larger than any digit so all digits
|
||||||
# will sort in front. Non-digits will sort according to their ICU first letter
|
# will sort in front. Non-digits will sort according to their ICU first letter
|
||||||
@ -155,16 +170,18 @@ def sort_key_for_name_and_first_letter(x):
|
|||||||
return (c if numeric_collation and c.isdigit() else '9999999999',
|
return (c if numeric_collation and c.isdigit() else '9999999999',
|
||||||
collation_order(v2), sort_key(v1))
|
collation_order(v2), sort_key(v1))
|
||||||
|
|
||||||
|
def sort_key_for_name(x, hierarchical_categories={}):
|
||||||
|
v = x.sort or x.name
|
||||||
|
if x.category not in hierarchical_categories:
|
||||||
|
return sort_key(v)
|
||||||
|
return sort_key(v.replace('.', '\t'))
|
||||||
|
|
||||||
|
|
||||||
category_sort_keys = {True:{}, False: {}}
|
category_sort_keys = {True:{}, False: {}}
|
||||||
category_sort_keys[True]['popularity'] = category_sort_keys[False]['popularity'] = \
|
category_sort_keys[True]['popularity'] = category_sort_keys[False]['popularity'] = sort_key_for_popularity
|
||||||
lambda x:(-getattr(x, 'count', 0), sort_key(x.sort or x.name))
|
category_sort_keys[True]['rating'] = category_sort_keys[False]['rating'] = sort_key_for_rating
|
||||||
category_sort_keys[True]['rating'] = category_sort_keys[False]['rating'] = \
|
category_sort_keys[True]['name'] = sort_key_for_name_and_first_letter
|
||||||
lambda x:(-getattr(x, 'avg_rating', 0.0), sort_key(x.sort or x.name))
|
category_sort_keys[False]['name'] = sort_key_for_name
|
||||||
category_sort_keys[True]['name'] = \
|
|
||||||
sort_key_for_name_and_first_letter
|
|
||||||
category_sort_keys[False]['name'] = \
|
|
||||||
lambda x:sort_key(x.sort or x.name)
|
|
||||||
|
|
||||||
|
|
||||||
# Various parts of calibre depend on the the order of fields in the returned
|
# Various parts of calibre depend on the the order of fields in the returned
|
||||||
@ -175,6 +192,7 @@ def get_categories(dbcache, sort='name', book_ids=None, first_letter_sort=False)
|
|||||||
if sort not in CATEGORY_SORTS:
|
if sort not in CATEGORY_SORTS:
|
||||||
raise ValueError('sort ' + sort + ' not a valid value')
|
raise ValueError('sort ' + sort + ' not a valid value')
|
||||||
|
|
||||||
|
hierarchical_categories = set(dbcache.pref('categories_using_hierarchy', []))
|
||||||
fm = dbcache.field_metadata
|
fm = dbcache.field_metadata
|
||||||
book_rating_map = dbcache.fields['rating'].book_value_map
|
book_rating_map = dbcache.fields['rating'].book_value_map
|
||||||
lang_map = dbcache.fields['languages'].book_value_map
|
lang_map = dbcache.fields['languages'].book_value_map
|
||||||
@ -217,7 +235,9 @@ def get_categories(dbcache, sort='name', book_ids=None, first_letter_sort=False)
|
|||||||
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)
|
||||||
cats.sort(key=category_sort_keys[first_letter_sort][sort_on], reverse=reverse)
|
cats.sort(key=partial(category_sort_keys[first_letter_sort][sort_on],
|
||||||
|
hierarchical_categories=hierarchical_categories),
|
||||||
|
reverse=reverse)
|
||||||
categories[category] = cats
|
categories[category] = cats
|
||||||
|
|
||||||
# Needed for legacy databases that have multiple ratings that
|
# Needed for legacy databases that have multiple ratings that
|
||||||
@ -295,7 +315,8 @@ def get_categories(dbcache, sort='name', book_ids=None, first_letter_sort=False)
|
|||||||
items.append(taglist[label][n])
|
items.append(taglist[label][n])
|
||||||
# else: do nothing, to not include nodes w zero counts
|
# else: do nothing, to not include nodes w zero counts
|
||||||
cat_name = '@' + user_cat # add the '@' to avoid name collision
|
cat_name = '@' + user_cat # add the '@' to avoid name collision
|
||||||
items.sort(key=category_sort_keys[False][sort])
|
items.sort(key=partial(category_sort_keys[False][sort],
|
||||||
|
hierarchical_categories=hierarchical_categories))
|
||||||
categories[cat_name] = items
|
categories[cat_name] = items
|
||||||
|
|
||||||
# ### Finally, the saved searches category ####
|
# ### Finally, the saved searches category ####
|
||||||
|
Loading…
x
Reference in New Issue
Block a user