CS Book Details: Show series

This commit is contained in:
Kovid Goyal 2016-02-17 16:15:44 +05:30
parent f076df0121
commit 6cadb702e9
3 changed files with 72 additions and 10 deletions

View File

@ -4,12 +4,13 @@
from __future__ import (unicode_literals, division, absolute_import, from __future__ import (unicode_literals, division, absolute_import,
print_function) print_function)
import re, hashlib, random import re, hashlib, random, os
from functools import partial from functools import partial
from threading import Lock from threading import Lock
from json import load as load_json_file from json import load as load_json_file
from calibre import prepare_string_for_xml, as_unicode from calibre import prepare_string_for_xml, as_unicode
from calibre.constants import config_dir
from calibre.customize.ui import available_input_formats from calibre.customize.ui import available_input_formats
from calibre.db.view import sanitize_sort_field_name from calibre.db.view import sanitize_sort_field_name
from calibre.srv.ajax import get_db, search_result from calibre.srv.ajax import get_db, search_result
@ -84,6 +85,21 @@ def get_basic_query_data(ctx, query):
sorts, orders = ['timestamp'], ['desc'] sorts, orders = ['timestamp'], ['desc']
return library_id, db, sorts, orders return library_id, db, sorts, orders
_use_roman = None
def get_use_roman():
global _use_roman
if _use_roman is None:
try:
with lopen(os.path.join(config_dir, 'gui.py'), 'rb') as f:
raw = f.read()
except EnvironmentError:
_use_roman = False
else:
m = re.search(br'use_roman_numerals_for_series_number\s*=\s*(True|False)', raw)
_use_roman = m is not None and m.group(1) == b'True'
return _use_roman
DEFAULT_NUMBER_OF_BOOKS = 50 DEFAULT_NUMBER_OF_BOOKS = 50
@endpoint('/interface-data/init', postprocess=json) @endpoint('/interface-data/init', postprocess=json)
@ -101,6 +117,7 @@ def interface_data(ctx, rd):
'gui_pubdate_display_format':tweaks['gui_pubdate_display_format'], 'gui_pubdate_display_format':tweaks['gui_pubdate_display_format'],
'gui_timestamp_display_format':tweaks['gui_timestamp_display_format'], 'gui_timestamp_display_format':tweaks['gui_timestamp_display_format'],
'gui_last_modified_display_format':tweaks['gui_last_modified_display_format'], 'gui_last_modified_display_format':tweaks['gui_last_modified_display_format'],
'use_roman_numerals_for_series_number': get_use_roman(),
} }
ans['library_map'], ans['default_library'] = ctx.library_map ans['library_map'], ans['default_library'] = ctx.library_map
ud = {} ud = {}

View File

@ -11,6 +11,7 @@ from book_list.globals import get_boss
from modals import error_dialog from modals import error_dialog
from widgets import create_spinner, create_button from widgets import create_spinner, create_button
from date import format_date from date import format_date
from utils import fmt_sidx
bd_counter = 0 bd_counter = 0
@ -37,15 +38,6 @@ def get_preferred_format(metadata, output_format, input_formats):
IGNORED_FIELDS = {'title', 'id', 'urls_from_identifiers', 'lang_names', 'last_modified'} IGNORED_FIELDS = {'title', 'id', 'urls_from_identifiers', 'lang_names', 'last_modified'}
def allowed_fields(field):
if str.endswith(field, '_index'):
return False
if str.startswith(field, '#'):
return True
if field in IGNORED_FIELDS or str.endswith(field, '_sort'):
return False
return True
default_sort = {f:i+1 for i, f in enumerate(('title', 'title_sort', 'authors', 'author_sort', 'series', 'rating', 'pubdate', 'tags', 'timestamp', 'pubdate', 'identifiers', 'languages', 'publisher', 'last_modified'))} default_sort = {f:i+1 for i, f in enumerate(('title', 'title_sort', 'authors', 'author_sort', 'series', 'rating', 'pubdate', 'tags', 'timestamp', 'pubdate', 'identifiers', 'languages', 'publisher', 'last_modified'))}
default_sort['formats'] = 999 default_sort['formats'] = 999
@ -69,6 +61,17 @@ def read_format(ev):
get_boss().ui.book_details_panel.read_format(fmt) get_boss().ui.book_details_panel.read_format(fmt)
def render_metadata(mi, interface_data, table, field_list=None): def render_metadata(mi, interface_data, table, field_list=None):
def allowed_fields(field):
if str.endswith(field, '_index'):
fm = interface_data.field_metadata[field[:-len('_index')]]
if fm and fm.datatype == 'series':
return False
if str.startswith(field, '#'):
return True
if field in IGNORED_FIELDS or str.endswith(field, '_sort'):
return False
return True
fields = field_list or sorted(filter(allowed_fields, mi), key=field_sorter(interface_data.field_metadata)) fields = field_list or sorted(filter(allowed_fields, mi), key=field_sorter(interface_data.field_metadata))
comments = [] comments = []
@ -177,6 +180,19 @@ def render_metadata(mi, interface_data, table, field_list=None):
fmt = interface_data['gui_' + field + '_display_format'] or (fm['display'] or {}).date_format fmt = interface_data['gui_' + field + '_display_format'] or (fm['display'] or {}).date_format
add_row(name, format_date(val, fmt)) add_row(name, format_date(val, fmt))
def process_series(field, fm, name, val):
if val:
ifield = field + '_index'
try:
ival = float(mi[ifield])
except Exception:
ival = 1.0
ival = fmt_sidx(ival, use_roman=interface_data.use_roman_numerals_for_series_number)
table.appendChild(E.tr(E.td(name + ':'), E.td()))
table.lastChild.lastChild.appendChild(E.span(ival, _(' of '), E.a(
data_search=JSON.stringify([name, val]), onclick=execute_search,
title=str.format(_('Click to see books with {0}: {1}'), name, val), href='javascript: void(0)', val)))
def process_field(field, fm): def process_field(field, fm):
name = fm.name or field name = fm.name or field
datatype = fm.datatype datatype = fm.datatype
@ -201,6 +217,8 @@ def render_metadata(mi, interface_data, table, field_list=None):
func = process_languages func = process_languages
elif datatype == 'datetime': elif datatype == 'datetime':
func = process_datetime func = process_datetime
elif datatype == 'series':
func = process_series
if func: if func:
func(field, fm, name, val) func(field, fm, name, val)
else: else:

View File

@ -54,3 +54,30 @@ def parse_url_params(url=None, allow_multiple=False):
else: else:
ans[key] = val ans[key] = val
return ans return ans
_roman = list(zip(
[1000,900,500,400,100,90,50,40,10,9,5,4,1],
["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"]
))
def roman(num):
if num <= 0 or num >= 4000 or int(num) != num:
return num + ''
result = []
for d, r in _roman:
while num >= d:
result.append(r)
num -= d
return result.join('')
def fmt_sidx(val, fmt='{:.2f}', use_roman=True):
if val is undefined or val is None or val == '':
return '1'
if int(val) == float(val):
if use_roman:
return roman(val)
return int(val) + ''
return str.format(fmt, float(val))
if __name__ == '__main__':
print(fmt_sidx(10), fmt_sidx(1.2))