Composite column bool sorting

This commit is contained in:
Kovid Goyal 2013-08-25 11:17:18 +05:30
parent 521320657d
commit f8463a2ddc
4 changed files with 35 additions and 22 deletions

View File

@ -15,12 +15,16 @@ from functools import partial
from calibre.db.tables import ONE_ONE, MANY_ONE, MANY_MANY, null
from calibre.db.write import Writer
from calibre.db.utils import force_to_bool
from calibre.ebooks.metadata import title_sort, author_to_author_sort
from calibre.utils.config_base import tweaks
from calibre.utils.icu import sort_key
from calibre.utils.date import UNDEFINED_DATE, clean_date_for_sort, parse_date
from calibre.utils.localization import calibre_langcode_to_name
def bool_sort_key(bools_are_tristate):
return (lambda x:{True: 1, False: 2, None: 3}.get(x, 3)) if bools_are_tristate else lambda x:{True: 1, False: 2, None: 2}.get(x, 2)
class Field(object):
is_many = False
@ -44,10 +48,7 @@ class Field(object):
self._default_sort_key = 0
elif dt == 'bool':
self._default_sort_key = None
if bools_are_tristate:
self._sort_key = lambda x:{True: 1, False: 2, None: 3}.get(x, 3)
else:
self._sort_key = lambda x:{True: 1, False: 2, None: 2}.get(x, 2)
self._sort_key = bool_sort_key(bools_are_tristate)
elif dt == 'datetime':
self._default_sort_key = UNDEFINED_DATE
if tweaks['sort_dates_using_visible_fields']:
@ -178,8 +179,8 @@ class CompositeField(OneToOneField):
is_composite = True
SIZE_SUFFIX_MAP = {suffix:i for i, suffix in enumerate(('', 'K', 'M', 'G', 'T', 'P', 'E'))}
def __init__(self, *args, **kwargs):
OneToOneField.__init__(self, *args, **kwargs)
def __init__(self, name, table, bools_are_tristate):
OneToOneField.__init__(self, name, table, bools_are_tristate)
self._render_cache = {}
self._lock = Lock()
@ -200,6 +201,10 @@ class CompositeField(OneToOneField):
fmt = m.get('display', {}).get('date_format', None)
self._filter_date = partial(clean_date_for_sort, fmt=fmt)
self._sort_key = self.date_sort_key
elif composite_sort == 'bool':
self._default_sort_key = None
self._bool_sort_key = bool_sort_key(bools_are_tristate)
self._sort_key = self.bool_sort_key
else:
self._sort_key = sort_key
@ -221,6 +226,9 @@ class CompositeField(OneToOneField):
val = UNDEFINED_DATE
return val
def bool_sort_key(self, val):
return self._bool_sort_key(force_to_bool(val))
def render_composite(self, book_id, mi):
with self._lock:
ans = self._render_cache.get(book_id, None)

View File

@ -13,6 +13,7 @@ from datetime import timedelta
from collections import deque
from calibre.constants import preferred_encoding
from calibre.db.utils import force_to_bool
from calibre.utils.config_base import prefs
from calibre.utils.date import parse_date, UNDEFINED_DATE, now, dt_as_local
from calibre.utils.icu import primary_find, sort_key
@ -25,22 +26,6 @@ REGEXP_MATCH = 2
# Utils {{{
def force_to_bool(val):
if isinstance(val, (str, unicode)):
try:
val = icu_lower(val)
if not val:
val = None
elif val in [_('yes'), _('checked'), 'true', 'yes']:
val = True
elif val in [_('no'), _('unchecked'), 'false', 'no']:
val = False
else:
val = bool(int(val))
except:
val = None
return val
def _matchkind(query):
matchkind = CONTAINS_MATCH
if (len(query) > 1):

View File

@ -564,6 +564,7 @@ class ReadingTest(BaseTest):
cache.create_custom_column('size', 'CC4', 'composite', False, display={'composite_template': '{#float:human_readable()}', 'composite_sort':'number'})
cache.create_custom_column('ccdate', 'CC5', 'composite', False,
display={'composite_template': '{pubdate:format_date(d-M-yy)}', 'composite_sort':'date'})
cache.create_custom_column('bool', 'CC6', 'composite', False, display={'composite_template': '{#yesno}', 'composite_sort':'bool'})
cache = self.init_cache()
# Test searching
@ -581,5 +582,8 @@ class ReadingTest(BaseTest):
# Test date sorting
cache.set_field('pubdate', {1:p('2001-2-6'), 2:p('2001-10-6'), 3:p('2001-6-6')})
self.assertEqual([1, 3, 2], cache.multisort([('#ccdate', True)]))
# Test bool sorting
self.assertEqual([2, 1, 3], cache.multisort([('#bool', True)]))
# }}}

View File

@ -14,6 +14,22 @@ from threading import Lock
from calibre import as_unicode, prints
from calibre.constants import cache_dir
def force_to_bool(val):
if isinstance(val, (str, unicode)):
try:
val = icu_lower(val)
if not val:
val = None
elif val in [_('yes'), _('checked'), 'true', 'yes']:
val = True
elif val in [_('no'), _('unchecked'), 'false', 'no']:
val = False
else:
val = bool(int(val))
except:
val = None
return val
Entry = namedtuple('Entry', 'path size timestamp thumbnail_size')
class CacheError(Exception):
pass