mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Composite column bool sorting
This commit is contained in:
parent
521320657d
commit
f8463a2ddc
@ -15,12 +15,16 @@ from functools import partial
|
|||||||
|
|
||||||
from calibre.db.tables import ONE_ONE, MANY_ONE, MANY_MANY, null
|
from calibre.db.tables import ONE_ONE, MANY_ONE, MANY_MANY, null
|
||||||
from calibre.db.write import Writer
|
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.ebooks.metadata import title_sort, author_to_author_sort
|
||||||
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
|
||||||
from calibre.utils.date import UNDEFINED_DATE, clean_date_for_sort, parse_date
|
from calibre.utils.date import UNDEFINED_DATE, clean_date_for_sort, parse_date
|
||||||
from calibre.utils.localization import calibre_langcode_to_name
|
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):
|
class Field(object):
|
||||||
|
|
||||||
is_many = False
|
is_many = False
|
||||||
@ -44,10 +48,7 @@ class Field(object):
|
|||||||
self._default_sort_key = 0
|
self._default_sort_key = 0
|
||||||
elif dt == 'bool':
|
elif dt == 'bool':
|
||||||
self._default_sort_key = None
|
self._default_sort_key = None
|
||||||
if bools_are_tristate:
|
self._sort_key = bool_sort_key(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)
|
|
||||||
elif dt == 'datetime':
|
elif dt == 'datetime':
|
||||||
self._default_sort_key = UNDEFINED_DATE
|
self._default_sort_key = UNDEFINED_DATE
|
||||||
if tweaks['sort_dates_using_visible_fields']:
|
if tweaks['sort_dates_using_visible_fields']:
|
||||||
@ -178,8 +179,8 @@ class CompositeField(OneToOneField):
|
|||||||
is_composite = True
|
is_composite = True
|
||||||
SIZE_SUFFIX_MAP = {suffix:i for i, suffix in enumerate(('', 'K', 'M', 'G', 'T', 'P', 'E'))}
|
SIZE_SUFFIX_MAP = {suffix:i for i, suffix in enumerate(('', 'K', 'M', 'G', 'T', 'P', 'E'))}
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, name, table, bools_are_tristate):
|
||||||
OneToOneField.__init__(self, *args, **kwargs)
|
OneToOneField.__init__(self, name, table, bools_are_tristate)
|
||||||
|
|
||||||
self._render_cache = {}
|
self._render_cache = {}
|
||||||
self._lock = Lock()
|
self._lock = Lock()
|
||||||
@ -200,6 +201,10 @@ class CompositeField(OneToOneField):
|
|||||||
fmt = m.get('display', {}).get('date_format', None)
|
fmt = m.get('display', {}).get('date_format', None)
|
||||||
self._filter_date = partial(clean_date_for_sort, fmt=fmt)
|
self._filter_date = partial(clean_date_for_sort, fmt=fmt)
|
||||||
self._sort_key = self.date_sort_key
|
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:
|
else:
|
||||||
self._sort_key = sort_key
|
self._sort_key = sort_key
|
||||||
|
|
||||||
@ -221,6 +226,9 @@ class CompositeField(OneToOneField):
|
|||||||
val = UNDEFINED_DATE
|
val = UNDEFINED_DATE
|
||||||
return val
|
return val
|
||||||
|
|
||||||
|
def bool_sort_key(self, val):
|
||||||
|
return self._bool_sort_key(force_to_bool(val))
|
||||||
|
|
||||||
def render_composite(self, book_id, mi):
|
def render_composite(self, book_id, mi):
|
||||||
with self._lock:
|
with self._lock:
|
||||||
ans = self._render_cache.get(book_id, None)
|
ans = self._render_cache.get(book_id, None)
|
||||||
|
@ -13,6 +13,7 @@ from datetime import timedelta
|
|||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
from calibre.constants import preferred_encoding
|
from calibre.constants import preferred_encoding
|
||||||
|
from calibre.db.utils import force_to_bool
|
||||||
from calibre.utils.config_base import prefs
|
from calibre.utils.config_base import prefs
|
||||||
from calibre.utils.date import parse_date, UNDEFINED_DATE, now, dt_as_local
|
from calibre.utils.date import parse_date, UNDEFINED_DATE, now, dt_as_local
|
||||||
from calibre.utils.icu import primary_find, sort_key
|
from calibre.utils.icu import primary_find, sort_key
|
||||||
@ -25,22 +26,6 @@ REGEXP_MATCH = 2
|
|||||||
|
|
||||||
# Utils {{{
|
# 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):
|
def _matchkind(query):
|
||||||
matchkind = CONTAINS_MATCH
|
matchkind = CONTAINS_MATCH
|
||||||
if (len(query) > 1):
|
if (len(query) > 1):
|
||||||
|
@ -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('size', 'CC4', 'composite', False, display={'composite_template': '{#float:human_readable()}', 'composite_sort':'number'})
|
||||||
cache.create_custom_column('ccdate', 'CC5', 'composite', False,
|
cache.create_custom_column('ccdate', 'CC5', 'composite', False,
|
||||||
display={'composite_template': '{pubdate:format_date(d-M-yy)}', 'composite_sort':'date'})
|
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()
|
cache = self.init_cache()
|
||||||
# Test searching
|
# Test searching
|
||||||
@ -581,5 +582,8 @@ class ReadingTest(BaseTest):
|
|||||||
# Test date sorting
|
# Test date sorting
|
||||||
cache.set_field('pubdate', {1:p('2001-2-6'), 2:p('2001-10-6'), 3:p('2001-6-6')})
|
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)]))
|
self.assertEqual([1, 3, 2], cache.multisort([('#ccdate', True)]))
|
||||||
|
|
||||||
|
# Test bool sorting
|
||||||
|
self.assertEqual([2, 1, 3], cache.multisort([('#bool', True)]))
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
@ -14,6 +14,22 @@ from threading import Lock
|
|||||||
from calibre import as_unicode, prints
|
from calibre import as_unicode, prints
|
||||||
from calibre.constants import cache_dir
|
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')
|
Entry = namedtuple('Entry', 'path size timestamp thumbnail_size')
|
||||||
class CacheError(Exception):
|
class CacheError(Exception):
|
||||||
pass
|
pass
|
||||||
|
Loading…
x
Reference in New Issue
Block a user