Generate correct search expressions for half stars when clicking the Tag Browser entries

This commit is contained in:
Kovid Goyal 2016-09-05 08:52:03 +05:30
parent 93b727818b
commit 27499c9188
5 changed files with 34 additions and 10 deletions

View File

@ -77,7 +77,10 @@ class Field(object):
self.default_value = {} if name == 'identifiers' else () if self.is_multiple else None
self.category_formatter = type(u'')
if dt == 'rating':
self.category_formatter = partial(rating_to_stars, allow_half_stars=self.metadata['display'].get('allow_half_stars', False))
if self.metadata['display'].get('allow_half_stars', False):
self.category_formatter = lambda x: rating_to_stars(x, True)
else:
self.category_formatter = rating_to_stars
elif name == 'languages':
self.category_formatter = calibre_langcode_to_name
self.writer = Writer(self)

View File

@ -397,11 +397,9 @@ def check_doi(doi):
def rating_to_stars(value, allow_half_stars=False, star=u'', half=u'½'):
r = max(0, min(int(value or 0), 10))
if allow_half_stars:
ans = u'' * (r // 2)
ans = star * (r // 2)
if r % 2:
ans += u'½'
ans += half
else:
ans = u'' * int(r/2.0)
ans = star * int(r/2.0)
return ans

View File

@ -15,6 +15,7 @@ from PyQt5.Qt import (QAbstractItemModel, QIcon, QFont, Qt,
QMimeData, QModelIndex, pyqtSignal, QObject)
from calibre.constants import config_dir
from calibre.ebooks.metadata import rating_to_stars
from calibre.gui2 import gprefs, config, error_dialog, file_icon_provider
from calibre.db.categories import Tag
from calibre.utils.config import tweaks
@ -1294,6 +1295,7 @@ class TagsModel(QAbstractItemModel): # {{{
# They will be 'checked' in both places, but we want to put the node
# into the search string only once. The nodes_seen set helps us do that
nodes_seen = set()
stars = rating_to_stars(3, True)
node_searches = {TAG_SEARCH_STATES['mark_plus'] : 'true',
TAG_SEARCH_STATES['mark_plusplus'] : '.true',
@ -1351,8 +1353,11 @@ class TagsModel(QAbstractItemModel): # {{{
if self.db.field_metadata[tag.category]['is_csp']:
add_colon = True
if tag.name and tag.name[0] in u'★½': # char is a star or a half. Assume rating
ans.append('%s%s:%s'%(prefix, category, len(tag.name)))
if tag.name and tag.name[0] in stars: # char is a star or a half. Assume rating
rnum = len(tag.name)
if tag.name.endswith(stars[-1]):
rnum = '%s.5' % (rnum - 1)
ans.append('%s%s:%s'%(prefix, category, rnum))
else:
name = tag.original_name
use_prefix = tag.state in [TAG_SEARCH_STATES['mark_plusplus'],

View File

@ -9,6 +9,7 @@ from elementmaker import E
from gettext import gettext as _
from widgets import create_button, create_spinner, Breadcrumbs
from modals import show_modal
from utils import rating_to_stars
from book_list.globals import get_boss, get_session_data
from book_list.theme import get_color, get_font_size
@ -224,6 +225,7 @@ class SearchPanel:
return ''
search_state = {'plus':'true', 'plusplus':'.true', 'minus':'false', 'minusminus':'.false'}[state]
stars = rating_to_stars(3, True)
if item.is_category:
category = item.category
@ -256,9 +258,12 @@ class SearchPanel:
return expr
category = 'tags' if item.category is 'news' else item.category
if item.name and item.name[0] in '★½':
if item.name and item.name[0] in stars:
# Assume ratings
expr = '{}:{}'.format(category, item.name.length)
rnum = item.name.length
if item.name.endswith(stars[-1]):
rnum = '{}.5'.format(rnum - 1)
expr = '{}:{}'.format(category, rnum)
else:
fm = self.interface_data.field_metadata[item.category]
suffix = ':' if fm and fm.is_csp else ''

View File

@ -69,6 +69,16 @@ def fmt_sidx(val, fmt='{:.2f}', use_roman=True):
return int(val) + ''
return fmt.format(float(val))
def rating_to_stars(value, allow_half_stars=False, star='★', half='½'):
r = max(0, min(int(value or 0), 10))
if allow_half_stars:
ans = star.repeat(r // 2)
if r % 2:
ans += half
else:
ans = star.repeat(int(r/2.0))
return ans
def human_readable(size, sep=' '):
divisor, suffix = 1, "B"
for i, candidate in enumerate(('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB')):
@ -142,5 +152,8 @@ def uniq(vals):
return ans
if __name__ is '__main__':
from pythonize import strings
strings()
print(rating_to_stars(3, True))
print(fmt_sidx(10), fmt_sidx(1.2))
print(list(map(human_readable, [1, 1024.0, 1025, 1024*1024*2.3])))