mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Switch to using string functions as methods
This commit is contained in:
parent
1a28db1073
commit
05c637cba7
@ -43,13 +43,13 @@ default_sort['formats'] = 999
|
|||||||
|
|
||||||
def field_sorter(field_metadata):
|
def field_sorter(field_metadata):
|
||||||
return def(field):
|
return def(field):
|
||||||
lvl = str.format('{:03d}', default_sort[field] or 998)
|
lvl = '{:03d}'.format(default_sort[field] or 998)
|
||||||
fm = (field_metadata[field] or {})[field] or {}
|
fm = (field_metadata[field] or {})[field] or {}
|
||||||
return lvl + (fm.name or 'zzzzz')
|
return lvl + (fm.name or 'zzzzz')
|
||||||
|
|
||||||
def execute_search(ev):
|
def execute_search(ev):
|
||||||
name, val = JSON.parse(ev.currentTarget.getAttribute('data-search'))
|
name, val = JSON.parse(ev.currentTarget.getAttribute('data-search'))
|
||||||
search = str.format('{}:"={}"', name, str.replace(val, '"', r'\"'))
|
search = '{}:"={}"'.format(name, str.replace(val, '"', r'\"'))
|
||||||
get_boss().ui.books_view.change_search(search)
|
get_boss().ui.books_view.change_search(search)
|
||||||
|
|
||||||
def download_format(ev):
|
def download_format(ev):
|
||||||
@ -62,13 +62,13 @@ def read_format(ev):
|
|||||||
|
|
||||||
def render_metadata(mi, interface_data, table, field_list=None):
|
def render_metadata(mi, interface_data, table, field_list=None):
|
||||||
def allowed_fields(field):
|
def allowed_fields(field):
|
||||||
if str.endswith(field, '_index'):
|
if field.endswith('_index'):
|
||||||
fm = interface_data.field_metadata[field[:-len('_index')]]
|
fm = interface_data.field_metadata[field[:-len('_index')]]
|
||||||
if fm and fm.datatype is 'series':
|
if fm and fm.datatype is 'series':
|
||||||
return False
|
return False
|
||||||
if str.startswith(field, '#'):
|
if field.startswith('#'):
|
||||||
return True
|
return True
|
||||||
if field in IGNORED_FIELDS or str.endswith(field, '_sort'):
|
if field in IGNORED_FIELDS or field.endswith('_sort'):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ def render_metadata(mi, interface_data, table, field_list=None):
|
|||||||
if is_searchable:
|
if is_searchable:
|
||||||
table.lastChild.lastChild.appendChild(E.a(
|
table.lastChild.lastChild.appendChild(E.a(
|
||||||
data_search=JSON.stringify([is_searchable, v]), onclick=execute_search,
|
data_search=JSON.stringify([is_searchable, v]), onclick=execute_search,
|
||||||
title=str.format(_('Click to see books with {0}: {1}'), name, v), href='javascript: void(0)', v))
|
title=_('Click to see books with {0}: {1}').format(name, v), href='javascript: void(0)', v))
|
||||||
else:
|
else:
|
||||||
if v.appendChild:
|
if v.appendChild:
|
||||||
table.lastChild.lastChild.appendChild(v)
|
table.lastChild.lastChild.appendChild(v)
|
||||||
@ -106,7 +106,7 @@ def render_metadata(mi, interface_data, table, field_list=None):
|
|||||||
add_row(name, val, is_html=True)
|
add_row(name, val, is_html=True)
|
||||||
return
|
return
|
||||||
if fm.is_multiple and fm.is_multiple.list_to_ui:
|
if fm.is_multiple and fm.is_multiple.list_to_ui:
|
||||||
all_vals = filter(None, map(str.strip, str.split(val, fm.is_multiple.list_to_ui)))
|
all_vals = filter(None, map(str.strip, val.split(fm.is_multiple.list_to_ui)))
|
||||||
add_row(name, all_vals, is_searchable=field, join=fm.is_multiple.list_to_ui)
|
add_row(name, all_vals, is_searchable=field, join=fm.is_multiple.list_to_ui)
|
||||||
else:
|
else:
|
||||||
add_row(name, val, is_searchable=field)
|
add_row(name, val, is_searchable=field)
|
||||||
@ -124,13 +124,13 @@ def render_metadata(mi, interface_data, table, field_list=None):
|
|||||||
td.appendChild(E.span(fmt, style='white-space: nowrap'))
|
td.appendChild(E.span(fmt, style='white-space: nowrap'))
|
||||||
if interface_data.input_formats[fmt] or interface_data.input_formats[fmt.replace('ORIGINAL_', '')]:
|
if interface_data.input_formats[fmt] or interface_data.input_formats[fmt.replace('ORIGINAL_', '')]:
|
||||||
td.lastChild.appendChild(E.a(
|
td.lastChild.appendChild(E.a(
|
||||||
title=str.format(_('Read this book in the {} format'), fmt),
|
title=_('Read this book in the {} format').format(fmt),
|
||||||
href='javascript:void(0)', style='padding-left: 1em',
|
href='javascript:void(0)', style='padding-left: 1em',
|
||||||
E.i(class_='fa fa-book'),
|
E.i(class_='fa fa-book'),
|
||||||
onclick=read_format, data_format=fmt
|
onclick=read_format, data_format=fmt
|
||||||
))
|
))
|
||||||
td.lastChild.appendChild(E.a(
|
td.lastChild.appendChild(E.a(
|
||||||
title=str.format(_('Download the {} format of this book'), fmt),
|
title=_('Download the {} format of this book').format(fmt),
|
||||||
href='javascript:void(0)', style='padding-left: 1em',
|
href='javascript:void(0)', style='padding-left: 1em',
|
||||||
E.i(class_='fa fa-cloud-download'),
|
E.i(class_='fa fa-cloud-download'),
|
||||||
onclick=download_format, data_format=fmt
|
onclick=download_format, data_format=fmt
|
||||||
@ -156,7 +156,7 @@ def render_metadata(mi, interface_data, table, field_list=None):
|
|||||||
idval = val[k]
|
idval = val[k]
|
||||||
x = url_map[k]
|
x = url_map[k]
|
||||||
if isinstance(x, list) and x.length is 2:
|
if isinstance(x, list) and x.length is 2:
|
||||||
td.appendChild(E.a(title=str.format('{}:{}', k, idval), target='_new', href=x[1], x[0]))
|
td.appendChild(E.a(title='{}:{}'.format(k, idval), target='_new', href=x[1], x[0]))
|
||||||
else:
|
else:
|
||||||
td.appendChild(E.span(k, ':', idval))
|
td.appendChild(E.span(k, ':', idval))
|
||||||
if k is not keys[-1]:
|
if k is not keys[-1]:
|
||||||
@ -169,7 +169,7 @@ def render_metadata(mi, interface_data, table, field_list=None):
|
|||||||
for k in val:
|
for k in val:
|
||||||
lang = mi.lang_names[k] or k
|
lang = mi.lang_names[k] or k
|
||||||
td.appendChild(E.a(lang,
|
td.appendChild(E.a(lang,
|
||||||
title=str.format(_('Click to see books with language: {}'), lang), href='javascript: void(0)',
|
title=_('Click to see books with language: {}').format(lang), href='javascript: void(0)',
|
||||||
data_search=JSON.stringify([field, k]), onclick=execute_search
|
data_search=JSON.stringify([field, k]), onclick=execute_search
|
||||||
))
|
))
|
||||||
if k is not val[-1]:
|
if k is not val[-1]:
|
||||||
@ -191,7 +191,7 @@ def render_metadata(mi, interface_data, table, field_list=None):
|
|||||||
table.appendChild(E.tr(E.td(name + ':'), E.td()))
|
table.appendChild(E.tr(E.td(name + ':'), E.td()))
|
||||||
table.lastChild.lastChild.appendChild(E.span(ival, _(' of '), E.a(
|
table.lastChild.lastChild.appendChild(E.span(ival, _(' of '), E.a(
|
||||||
data_search=JSON.stringify([field, val]), onclick=execute_search,
|
data_search=JSON.stringify([field, val]), onclick=execute_search,
|
||||||
title=str.format(_('Click to see books with {0}: {1}'), name, val), href='javascript: void(0)', val)))
|
title=_('Click to see books with {0}: {1}').format(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
|
||||||
@ -230,7 +230,7 @@ def render_metadata(mi, interface_data, table, field_list=None):
|
|||||||
elif datatype is 'int' or datatype is 'float':
|
elif datatype is 'int' or datatype is 'float':
|
||||||
fmt = (fm.display or {}).number_format
|
fmt = (fm.display or {}).number_format
|
||||||
if fmt:
|
if fmt:
|
||||||
val = str.format(fmt, val)
|
val = fmt.format(val)
|
||||||
else:
|
else:
|
||||||
val += ''
|
val += ''
|
||||||
add_row(name, val)
|
add_row(name, val)
|
||||||
@ -347,13 +347,12 @@ class BookDetailsPanel:
|
|||||||
self.current_book_id = int(book_id)
|
self.current_book_id = int(book_id)
|
||||||
metadata = self.interface_data.metadata[book_id]
|
metadata = self.interface_data.metadata[book_id]
|
||||||
get_boss().ui.set_title(metadata.title)
|
get_boss().ui.set_title(metadata.title)
|
||||||
cover_url = str.format('get/cover/{}/{}', book_id, self.interface_data['library_id'])
|
cover_url = 'get/cover/{}/{}'.format(book_id, self.interface_data['library_id'])
|
||||||
alt = str.format(_('{} by {}'), metadata['title'], metadata['authors'].join(' & '))
|
alt = _('{} by {}').format(metadata['title'], metadata['authors'].join(' & '))
|
||||||
imgdiv = E.div(
|
imgdiv = E.div(
|
||||||
E.img(
|
E.img(
|
||||||
src=cover_url, alt=alt, title=alt, data_title=metadata['title'], data_authors=metadata['authors'].join(' & '),
|
src=cover_url, alt=alt, title=alt, data_title=metadata['title'], data_authors=metadata['authors'].join(' & '),
|
||||||
style=str.format(
|
style='border-radius: 20px; max-width: calc(100vw - 2em); max-height: calc(100vh - 4ex - {}); display: block; width:auto; height:auto; border-radius: 20px'.format(get_font_size('title')
|
||||||
'border-radius: 20px; max-width: calc(100vw - 2em); max-height: calc(100vh - 4ex - {}); display: block; width:auto; height:auto; border-radius: 20px', get_font_size('title')
|
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
imgdiv.firstChild.onerror = self.on_img_err.bind(self)
|
imgdiv.firstChild.onerror = self.on_img_err.bind(self)
|
||||||
@ -365,8 +364,8 @@ class BookDetailsPanel:
|
|||||||
))
|
))
|
||||||
container = c.lastChild.firstChild
|
container = c.lastChild.firstChild
|
||||||
read_button = create_button(_('Read'), 'book', self.read_book.bind(self), _('Read this book'))
|
read_button = create_button(_('Read'), 'book', self.read_book.bind(self), _('Read this book'))
|
||||||
download_button = create_button(_('Download'), 'cloud-download', self.download_book.bind(self), str.format(
|
download_button = create_button(_('Download'), 'cloud-download', self.download_book.bind(self),
|
||||||
_('Download this book in the {} format'), self.preferred_format(book_id)))
|
_('Download this book in the {} format').format(self.preferred_format(book_id)))
|
||||||
row = E.div(read_button, '\xa0\xa0\xa0', download_button, style='margin-bottom: 1ex')
|
row = E.div(read_button, '\xa0\xa0\xa0', download_button, style='margin-bottom: 1ex')
|
||||||
if not metadata.formats or not metadata.formats.length:
|
if not metadata.formats or not metadata.formats.length:
|
||||||
row.style.display = 'none'
|
row.style.display = 'none'
|
||||||
@ -385,7 +384,7 @@ class BookDetailsPanel:
|
|||||||
return get_preferred_format(self.interface_data.metadata[book_id], self.interface_data.output_format, self.interface_data.input_formats)
|
return get_preferred_format(self.interface_data.metadata[book_id], self.interface_data.output_format, self.interface_data.input_formats)
|
||||||
|
|
||||||
def download_format(self, fmt):
|
def download_format(self, fmt):
|
||||||
window.location = str.format('get/{}/{}/{}', fmt, self.current_book_id, self.interface_data.library_id)
|
window.location = 'get/{}/{}/{}'.format(fmt, self.current_book_id, self.interface_data.library_id)
|
||||||
|
|
||||||
def download_book(self):
|
def download_book(self):
|
||||||
book_id = self.current_book_id
|
book_id = self.current_book_id
|
||||||
|
@ -73,8 +73,8 @@ class Boss:
|
|||||||
def onerror(self, msg, script_url, line_number, column_number, error_object):
|
def onerror(self, msg, script_url, line_number, column_number, error_object):
|
||||||
console.log(error_object)
|
console.log(error_object)
|
||||||
try:
|
try:
|
||||||
fname = str.rpartition(script_url, '/')[-1] or script_url
|
fname = script_url.rpartition('/')[-1] or script_url
|
||||||
msg = msg + '<br><span style="font-size:smaller">' + str.format('Error at {}:{}:{}', fname, line_number, column_number or '') + '</span>'
|
msg = msg + '<br><span style="font-size:smaller">' + 'Error at {}:{}:{}'.format(fname, line_number, column_number or '') + '</span>'
|
||||||
details = ''
|
details = ''
|
||||||
if error_object and error_object.stack:
|
if error_object and error_object.stack:
|
||||||
details = error_object.stack
|
details = error_object.stack
|
||||||
@ -105,12 +105,12 @@ class Boss:
|
|||||||
self.read_ui.load_book(book_id, fmt, metadata)
|
self.read_ui.load_book(book_id, fmt, metadata)
|
||||||
|
|
||||||
def change_books(self, data):
|
def change_books(self, data):
|
||||||
data.search_result.sort = str.split(data.search_result.sort, ',')[:2].join(',')
|
data.search_result.sort = data.search_result.sort.split(',')[:2].join(',')
|
||||||
data.search_result.sort_order = str.split(data.search_result.sort_order, ',')[:2].join(',')
|
data.search_result.sort_order = data.search_result.sort_order.split(',')[:2].join(',')
|
||||||
sval = ''
|
sval = ''
|
||||||
for field, order in zip(str.split(data.search_result.sort, ','), str.split(data.search_result.sort_order, ',')):
|
for field, order in zip(data.search_result.sort.split(','), data.search_result.sort_order.split(',')):
|
||||||
sval += field + '.' + order + ','
|
sval += field + '.' + order + ','
|
||||||
get_session_data().set_library_option(self.interface_data.library_id, 'sort', str.rstrip(sval, ','))
|
get_session_data().set_library_option(self.interface_data.library_id, 'sort', sval.rstrip(','))
|
||||||
self.interface_data.metadata = data.metadata
|
self.interface_data.metadata = data.metadata
|
||||||
self.interface_data.search_result = data.search_result
|
self.interface_data.search_result = data.search_result
|
||||||
self.ui.refresh_books_view()
|
self.ui.refresh_books_view()
|
||||||
|
@ -133,7 +133,7 @@ class SpinBox(ConfigItem):
|
|||||||
)
|
)
|
||||||
container.appendChild(div)
|
container.appendChild(div)
|
||||||
control = div.lastChild
|
control = div.lastChild
|
||||||
for attr in str.split('min max step'):
|
for attr in 'min max step'.split(' '):
|
||||||
val = item_data[attr]
|
val = item_data[attr]
|
||||||
if val is not undefined and val is not None:
|
if val is not undefined and val is not None:
|
||||||
control.setAttribute(attr, '' + val)
|
control.setAttribute(attr, '' + val)
|
||||||
@ -202,7 +202,7 @@ class PrefsPanel:
|
|||||||
def onfocus(name):
|
def onfocus(name):
|
||||||
return def(ev):
|
return def(ev):
|
||||||
c = self.container
|
c = self.container
|
||||||
div = c.querySelector(str.format('div[data-name="{}"]', name))
|
div = c.querySelector('div[data-name="{}"]'.format(name))
|
||||||
div.lastChild.style.display = 'block'
|
div.lastChild.style.display = 'block'
|
||||||
|
|
||||||
for item in data:
|
for item in data:
|
||||||
|
@ -51,7 +51,7 @@ class SearchPanel:
|
|||||||
type='search', autosave='search-for-books-in-main-calibre-booklist', name='search-books',
|
type='search', autosave='search-for-books-in-main-calibre-booklist', name='search-books',
|
||||||
autocomplete='on', inputmode='latin',
|
autocomplete='on', inputmode='latin',
|
||||||
title=_('Search for books'), placeholder=_('Enter the search query'), spellcheck='false',
|
title=_('Search for books'), placeholder=_('Enter the search query'), spellcheck='false',
|
||||||
style=str.format("flex-grow: 10; padding: {} 0.5em; margin-right: 0.5em", BUTTON_VPADDING)
|
style="flex-grow: 10; padding: {} 0.5em; margin-right: 0.5em".format(BUTTON_VPADDING)
|
||||||
),
|
),
|
||||||
search_button
|
search_button
|
||||||
))
|
))
|
||||||
@ -96,7 +96,7 @@ class SearchPanel:
|
|||||||
self.currently_loading = None
|
self.currently_loading = None
|
||||||
sd = get_session_data()
|
sd = get_session_data()
|
||||||
query = {'library_id': self.interface_data.library_id}
|
query = {'library_id': self.interface_data.library_id}
|
||||||
for k in str.split('sort_tags_by partition_method collapse_at dont_collapse hide_empty_categories'):
|
for k in 'sort_tags_by partition_method collapse_at dont_collapse hide_empty_categories'.split(' '):
|
||||||
query[k] = sd.get(k) + ''
|
query[k] = sd.get(k) + ''
|
||||||
xhr = ajax('interface-data/tag-browser', self.on_data_fetched.bind(self), query=query, bypass_cache=False)
|
xhr = ajax('interface-data/tag-browser', self.on_data_fetched.bind(self), query=query, bypass_cache=False)
|
||||||
xhr.send()
|
xhr.send()
|
||||||
@ -169,11 +169,11 @@ class SearchPanel:
|
|||||||
data = node.data
|
data = node.data
|
||||||
tooltip = ''
|
tooltip = ''
|
||||||
if data.count is not undefined:
|
if data.count is not undefined:
|
||||||
tooltip += '\n' + str.format(_('Number of books in this category: {}'), data.count)
|
tooltip += '\n' + _('Number of books in this category: {}').format(data.count)
|
||||||
if data.avg_rating is not undefined:
|
if data.avg_rating is not undefined:
|
||||||
tooltip += '\n' + str.format(_('Average rating for books in this category: {:.1f}'), data.avg_rating)
|
tooltip += '\n' + _('Average rating for books in this category: {:.1f}').format(data.avg_rating)
|
||||||
div = E.div(
|
div = E.div(
|
||||||
title=str.lstrip(tooltip),
|
title=tooltip.lstrip(),
|
||||||
style="display:flex; align-items: stretch",
|
style="display:flex; align-items: stretch",
|
||||||
E.div(class_='tag-name',
|
E.div(class_='tag-name',
|
||||||
style='border-right:solid 1px currentColor; padding: 1ex; display:flex; align-items: center',
|
style='border-right:solid 1px currentColor; padding: 1ex; display:flex; align-items: center',
|
||||||
@ -237,19 +237,19 @@ class SearchPanel:
|
|||||||
if letters_seen.length:
|
if letters_seen.length:
|
||||||
charclass = letters_seen.join('')
|
charclass = letters_seen.join('')
|
||||||
if category is 'authors':
|
if category is 'authors':
|
||||||
expr = str.format(r'author_sort:"~(^[{0}])|(&\s*[{0}])"', charclass)
|
expr = r'author_sort:"~(^[{0}])|(&\s*[{0}])"'.format(charclass)
|
||||||
elif category is 'series':
|
elif category is 'series':
|
||||||
expr = str.format(r'series_sort:"~^[{0}]"', charclass)
|
expr = r'series_sort:"~^[{0}]"'.format(charclass)
|
||||||
else:
|
else:
|
||||||
expr = str.format(r'{0}:"~^[{1}]"', category, charclass)
|
expr = r'{0}:"~^[{1}]"'.format(category, charclass)
|
||||||
else:
|
else:
|
||||||
expr = str.format('{}:false', category)
|
expr = '{}:false'.format(category)
|
||||||
|
|
||||||
elif category is 'news':
|
elif category is 'news':
|
||||||
expr = str.format('tags:"={}"', item.name)
|
expr = 'tags:"={}"'.format(item.name)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return str.format('{}:{}', category, search_state)
|
return '{}:{}'.format(category, search_state)
|
||||||
|
|
||||||
if 'false' in search_state:
|
if 'false' in search_state:
|
||||||
expr = '(not ' + expr + ')'
|
expr = '(not ' + expr + ')'
|
||||||
@ -258,7 +258,7 @@ class SearchPanel:
|
|||||||
category = 'tags' if item.category is 'news' else item.category
|
category = 'tags' if item.category is 'news' else item.category
|
||||||
if item.name and item.name[0] is '★':
|
if item.name and item.name[0] is '★':
|
||||||
# Assume ratings
|
# Assume ratings
|
||||||
expr = str.format('{}:{}', category, item.name.length)
|
expr = '{}:{}'.format(category, item.name.length)
|
||||||
else:
|
else:
|
||||||
fm = self.interface_data.field_metadata[item.category]
|
fm = self.interface_data.field_metadata[item.category]
|
||||||
suffix = ':' if fm and fm.is_csp else ''
|
suffix = ':' if fm and fm.is_csp else ''
|
||||||
@ -270,7 +270,7 @@ class SearchPanel:
|
|||||||
name = '.' + name
|
name = '.' + name
|
||||||
if search_state is 'plusplus' or search_state is 'minusminus':
|
if search_state is 'plusplus' or search_state is 'minusminus':
|
||||||
name = '.' + name
|
name = '.' + name
|
||||||
expr = str.format('{}:"={}{}"', category, name, suffix)
|
expr = '{}:"={}{}"'.format(category, name, suffix)
|
||||||
|
|
||||||
if 'false' in search_state:
|
if 'false' in search_state:
|
||||||
expr = '(not ' + expr + ')'
|
expr = '(not ' + expr + ')'
|
||||||
@ -299,7 +299,7 @@ class SearchPanel:
|
|||||||
if data.count is not undefined:
|
if data.count is not undefined:
|
||||||
items.append(_('Count: ') + data.count)
|
items.append(_('Count: ') + data.count)
|
||||||
if data.avg_rating is not undefined:
|
if data.avg_rating is not undefined:
|
||||||
items.append(str.format(_('Rating: {:.1f}'), data.avg_rating))
|
items.append(_('Rating: {:.1f}').format(data.avg_rating))
|
||||||
suffix = ''
|
suffix = ''
|
||||||
if items.length:
|
if items.length:
|
||||||
suffix = ' [' + items.join(' ') + ']'
|
suffix = ' [' + items.join(' ') + ']'
|
||||||
@ -332,7 +332,7 @@ class SearchPanel:
|
|||||||
for text, search_type in items:
|
for text, search_type in items:
|
||||||
li = E.li(
|
li = E.li(
|
||||||
style='display:flex; align-items: center; margin-bottom:0.5ex; padding: 0.5ex; cursor:pointer',
|
style='display:flex; align-items: center; margin-bottom:0.5ex; padding: 0.5ex; cursor:pointer',
|
||||||
E.img(src=str.format('{}/{}.png', self.interface_data.icon_path, search_type), style='max-height: 2.5ex'),
|
E.img(src='{}/{}.png'.format(self.interface_data.icon_path, search_type), style='max-height: 2.5ex'),
|
||||||
E.span('\xa0' + text)
|
E.span('\xa0' + text)
|
||||||
)
|
)
|
||||||
li.addEventListener('click', add_to_search(node, search_type))
|
li.addEventListener('click', add_to_search(node, search_type))
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
DARK = '#39322B'
|
DARK = '#39322B'
|
||||||
LIGHT = '#F6F3E9'
|
LIGHT = '#F6F3E9'
|
||||||
LIGHT_DARKER = '#b6b3a8'
|
LIGHT_DARKER = '#b6b3a8'
|
||||||
LIGHT_GRADIENT = str.format('linear-gradient(to bottom, {}, {})', LIGHT, LIGHT_DARKER)
|
LIGHT_GRADIENT = 'linear-gradient(to bottom, {}, {})'.format(LIGHT, LIGHT_DARKER)
|
||||||
|
|
||||||
def get_color(name):
|
def get_color(name):
|
||||||
return {
|
return {
|
||||||
|
@ -71,8 +71,8 @@ class TopBar:
|
|||||||
clear(left)
|
clear(left)
|
||||||
title_elem = 'a' if callable(title_action) else 'span'
|
title_elem = 'a' if callable(title_action) else 'span'
|
||||||
left.appendChild(E.a(title=tooltip, E.i(class_='fa fa-' + icon_name + ' fa-fw')))
|
left.appendChild(E.a(title=tooltip, E.i(class_='fa fa-' + icon_name + ' fa-fw')))
|
||||||
left.appendChild(E(title_elem, title, title=title_tooltip, class_='top-bar-title', style=str.format(
|
left.appendChild(E(title_elem, title, title=title_tooltip, class_='top-bar-title',
|
||||||
'margin-left: {0}; font-weight: bold; padding-top: {1}; padding-bottom: {1}; vertical-align: middle', self.SPACING, self.VSPACING)))
|
style='margin-left: {0}; font-weight: bold; padding-top: {1}; padding-bottom: {1}; vertical-align: middle'.format(self.SPACING, self.VSPACING)))
|
||||||
if bar is self.bar:
|
if bar is self.bar:
|
||||||
a = left.firstChild
|
a = left.firstChild
|
||||||
if icon_name is 'heart':
|
if icon_name is 'heart':
|
||||||
|
@ -172,16 +172,16 @@ class BooksView:
|
|||||||
set_css(div, border='dashed 1px currentColor', border_radius='10px')
|
set_css(div, border='dashed 1px currentColor', border_radius='10px')
|
||||||
|
|
||||||
def cover_grid_item(self, book_id):
|
def cover_grid_item(self, book_id):
|
||||||
cover_url = str.format('get/thumb/{}/{}?sz={}x{}', book_id, self.interface_data['library_id'], THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT)
|
cover_url = 'get/thumb/{}/{}?sz={}x{}'.format(book_id, self.interface_data['library_id'], THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT)
|
||||||
metadata = self.interface_data['metadata'][book_id]
|
metadata = self.interface_data['metadata'][book_id]
|
||||||
alt = str.format(_('{} by {}'), metadata['title'], metadata['authors'].join(' & '))
|
alt = _('{} by {}').format(metadata['title'], metadata['authors'].join(' & '))
|
||||||
img = E.img(src=cover_url, alt=alt, title=alt, data_title=metadata['title'], data_authors=metadata['authors'].join(' & '),
|
img = E.img(src=cover_url, alt=alt, title=alt, data_title=metadata['title'], data_authors=metadata['authors'].join(' & '),
|
||||||
style='max-width: 100%; max-height: 100%; display: block; width:auto; height:auto; border-radius: 10px')
|
style='max-width: 100%; max-height: 100%; display: block; width:auto; height:auto; border-radius: 10px')
|
||||||
img.onerror = self.on_cover_grid_img_err.bind(self)
|
img.onerror = self.on_cover_grid_img_err.bind(self)
|
||||||
|
|
||||||
ans = E.div(
|
ans = E.div(
|
||||||
style=str.format(('margin: 10px; display: flex; align-content: flex-end; align-items: flex-end; justify-content: space-around;'
|
style=('margin: 10px; display: flex; align-content: flex-end; align-items: flex-end; justify-content: space-around;'
|
||||||
'width: 21vw; height: 28vw; max-width: {}px; max-height: {}px; min-width: {}px; min-height: {}px; cursor:pointer'),
|
'width: 21vw; height: 28vw; max-width: {}px; max-height: {}px; min-width: {}px; min-height: {}px; cursor:pointer').format(
|
||||||
THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT, THUMBNAIL_MAX_WIDTH // 2, THUMBNAIL_MAX_HEIGHT // 2),
|
THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT, THUMBNAIL_MAX_WIDTH // 2, THUMBNAIL_MAX_HEIGHT // 2),
|
||||||
data_book_id=str(book_id),
|
data_book_id=str(book_id),
|
||||||
img
|
img
|
||||||
@ -192,8 +192,8 @@ class BooksView:
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
def sort_panel_data(self, create_item):
|
def sort_panel_data(self, create_item):
|
||||||
current_sorted_field = str.partition(self.interface_data.search_result.sort, ',')[0]
|
current_sorted_field = self.interface_data.search_result.sort.partition(',')[0]
|
||||||
current_sorted_field_order = str.partition(self.interface_data.search_result.sort_order, ',')[0]
|
current_sorted_field_order = self.interface_data.search_result.sort_order.partition(',')[0]
|
||||||
new_sort_order = 'desc' if current_sorted_field_order is 'asc' else 'asc'
|
new_sort_order = 'desc' if current_sorted_field_order is 'asc' else 'asc'
|
||||||
if current_sorted_field is 'date':
|
if current_sorted_field is 'date':
|
||||||
current_sorted_field = 'timestamp'
|
current_sorted_field = 'timestamp'
|
||||||
@ -258,7 +258,7 @@ class BooksView:
|
|||||||
window.scrollTo(0, 0)
|
window.scrollTo(0, 0)
|
||||||
elif end_type is not 'abort':
|
elif end_type is not 'abort':
|
||||||
msg = xhr.error_html
|
msg = xhr.error_html
|
||||||
if xhr.status is 400 and str.startswith(xhr.responseText, 'Invalid search expression:'):
|
if xhr.status is 400 and xhr.responseText.startswith('Invalid search expression:'):
|
||||||
msg = _('The search expression could not be parsed: ') + xhr.responseText
|
msg = _('The search expression could not be parsed: ') + xhr.responseText
|
||||||
error_dialog(_('Could not change search query'), msg)
|
error_dialog(_('Could not change search query'), msg)
|
||||||
|
|
||||||
|
6
src/pyj/initialize.pyj
Normal file
6
src/pyj/initialize.pyj
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
from pythonize import strings
|
||||||
|
|
||||||
|
strings()
|
@ -142,7 +142,7 @@ class DB:
|
|||||||
req = self.idb.transaction(['files'], 'readwrite').objectStore('files').put(data, fname)
|
req = self.idb.transaction(['files'], 'readwrite').objectStore('files').put(data, fname)
|
||||||
req.onsuccess = def(event): proceed()
|
req.onsuccess = def(event): proceed()
|
||||||
req.onerror = def(event):
|
req.onerror = def(event):
|
||||||
proceed(str.format(_('Failed to store book data ({0}) with error: {1}'), name, get_error_details(event)))
|
proceed(_('Failed to store book data ({0}) with error: {1}').format(name, get_error_details(event)))
|
||||||
|
|
||||||
def finish_book(self, book, proceed):
|
def finish_book(self, book, proceed):
|
||||||
book.is_complete = True
|
book.is_complete = True
|
||||||
@ -154,8 +154,8 @@ class DB:
|
|||||||
|
|
||||||
def get_file(self, book, name, proceed):
|
def get_file(self, book, name, proceed):
|
||||||
key = file_store_name(book, name)
|
key = file_store_name(book, name)
|
||||||
err = str.format(_(
|
err = _(
|
||||||
'Failed to read the file {0} for the book {1} from the database'), name, book.metadata.title)
|
'Failed to read the file {0} for the book {1} from the database').format(name, book.metadata.title)
|
||||||
self.do_op(['files'], key, err, def (result):
|
self.do_op(['files'], key, err, def (result):
|
||||||
if not result:
|
if not result:
|
||||||
self.show_error(_('Cannot read book'), err)
|
self.show_error(_('Cannot read book'), err)
|
||||||
|
@ -42,10 +42,10 @@ def load_resources(db, book, root_name, previous_resources, proceed):
|
|||||||
w = book.manifest.cover_width or 600
|
w = book.manifest.cover_width or 600
|
||||||
h = book.manifest.cover_height or 800
|
h = book.manifest.cover_height or 800
|
||||||
ar = 'xMidYMid meet' # or 'none'
|
ar = 'xMidYMid meet' # or 'none'
|
||||||
data = str.replace(data, '__ar__', ar)
|
data = data.replace('__ar__', ar)
|
||||||
data = str.replace(data, '__viewbox__', '0 0 ' + w + ' ' + h)
|
data = data.replace('__viewbox__', '0 0 ' + w + ' ' + h)
|
||||||
data = str.replace(data, '__width__', w + '')
|
data = data.replace('__width__', w + '')
|
||||||
data = str.replace(data, '__height__', h + '')
|
data = data.replace('__height__', h + '')
|
||||||
ans[name] = v'[data, mimetype]'
|
ans[name] = v'[data, mimetype]'
|
||||||
if type(data) is 'string':
|
if type(data) is 'string':
|
||||||
find_virtualized_resources(data)
|
find_virtualized_resources(data)
|
||||||
@ -131,7 +131,7 @@ def finalize_resources(book, root_name, resource_data):
|
|||||||
break
|
break
|
||||||
if not resolved.length:
|
if not resolved.length:
|
||||||
unresolved = [name for name in resource_data if name not in blob_url_map]
|
unresolved = [name for name in resource_data if name not in blob_url_map]
|
||||||
print(str.format('ERROR: Could not resolve all dependencies of {} because of a cyclic dependency. Remaining deps: {}', root_name, unresolved))
|
print('ERROR: Could not resolve all dependencies of {} because of a cyclic dependency. Remaining deps: {}'.format(root_name, unresolved))
|
||||||
# Add the items anyway, without resolving remaining deps
|
# Add the items anyway, without resolving remaining deps
|
||||||
for name in resource_data:
|
for name in resource_data:
|
||||||
if name not in blob_url_map:
|
if name not in blob_url_map:
|
||||||
@ -172,7 +172,7 @@ def process_stack(stack, tag_map, ns_map, load_required, onload):
|
|||||||
attr = attr.replace('xlink:', '')
|
attr = attr.replace('xlink:', '')
|
||||||
for a in (src.a or v'[]'):
|
for a in (src.a or v'[]'):
|
||||||
if a[0] is attr:
|
if a[0] is attr:
|
||||||
loadable = str.startswith(a[1], 'blob:')
|
loadable = a[1].startswith('blob:')
|
||||||
break
|
break
|
||||||
if loadable:
|
if loadable:
|
||||||
load_required.add(node[0])
|
load_required.add(node[0])
|
||||||
|
@ -71,8 +71,8 @@ class ReadUI:
|
|||||||
'book-id': (self.current_book_id + ''),
|
'book-id': (self.current_book_id + ''),
|
||||||
'panel':'book-details'
|
'panel':'book-details'
|
||||||
}))
|
}))
|
||||||
a.textContent = str.format(_(
|
a.textContent = _(
|
||||||
'Click to go back to the details page for: {}'), self.current_metadata.title)
|
'Click to go back to the details page for: {}').format(self.current_metadata.title)
|
||||||
else:
|
else:
|
||||||
a.textContent = ''
|
a.textContent = ''
|
||||||
a.setAttribute('href', '')
|
a.setAttribute('href', '')
|
||||||
@ -80,8 +80,8 @@ class ReadUI:
|
|||||||
def init_ui(self):
|
def init_ui(self):
|
||||||
div = self.show_stack(self.progress_id)
|
div = self.show_stack(self.progress_id)
|
||||||
if self.current_metadata:
|
if self.current_metadata:
|
||||||
div.firstChild.textContent = str.format(_(
|
div.firstChild.textContent = _(
|
||||||
'Downloading {0} for offline reading, please wait...'), self.current_metadata.title)
|
'Downloading {0} for offline reading, please wait...').format(self.current_metadata.title)
|
||||||
else:
|
else:
|
||||||
div.firstChild.textContent = ''
|
div.firstChild.textContent = ''
|
||||||
pr = div.firstChild.nextSibling
|
pr = div.firstChild.nextSibling
|
||||||
@ -133,14 +133,14 @@ class ReadUI:
|
|||||||
if end_type is 'abort':
|
if end_type is 'abort':
|
||||||
return
|
return
|
||||||
if end_type is not 'load':
|
if end_type is not 'load':
|
||||||
return self.show_error(_('Failed to load book manifest'), str.format(
|
return self.show_error(_('Failed to load book manifest'),
|
||||||
_('Could not open {title} as book manifest failed to load, click "Show Details" for more information.'), title=self.current_metadata.title),
|
_('Could not open {title} as book manifest failed to load, click "Show Details" for more information.').format(title=self.current_metadata.title),
|
||||||
xhr.error_html)
|
xhr.error_html)
|
||||||
try:
|
try:
|
||||||
manifest = JSON.parse(xhr.responseText)
|
manifest = JSON.parse(xhr.responseText)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
return self.show_error(_('Failed to load book manifest'), str.format(
|
return self.show_error(_('Failed to load book manifest'),
|
||||||
_('The manifest for {title} is not valid'), title=self.current_metadata.title),
|
_('The manifest for {title} is not valid').format(title=self.current_metadata.title),
|
||||||
err.stack or err.toString())
|
err.stack or err.toString())
|
||||||
if manifest.version != RENDER_VERSION:
|
if manifest.version != RENDER_VERSION:
|
||||||
return self.show_error(_('calibre upgraded!'), _(
|
return self.show_error(_('calibre upgraded!'), _(
|
||||||
@ -162,8 +162,7 @@ class ReadUI:
|
|||||||
progress = document.getElementById(self.progress_id)
|
progress = document.getElementById(self.progress_id)
|
||||||
pbar = progress.firstChild.nextSibling
|
pbar = progress.firstChild.nextSibling
|
||||||
library_id, book_id, fmt = book.key
|
library_id, book_id, fmt = book.key
|
||||||
base_path = str.format(
|
base_path = 'book-file/{}/{}/{}/{}/'.format(encodeURIComponent(book_id), encodeURIComponent(fmt),
|
||||||
'book-file/{}/{}/{}/{}/', encodeURIComponent(book_id), encodeURIComponent(fmt),
|
|
||||||
encodeURIComponent(book.manifest.book_hash.size), encodeURIComponent(book.manifest.book_hash.mtime))
|
encodeURIComponent(book.manifest.book_hash.size), encodeURIComponent(book.manifest.book_hash.mtime))
|
||||||
query = {'library_id': library_id}
|
query = {'library_id': library_id}
|
||||||
progress_track = {}
|
progress_track = {}
|
||||||
@ -175,7 +174,7 @@ class ReadUI:
|
|||||||
for name in progress_track:
|
for name in progress_track:
|
||||||
x += progress_track[name]
|
x += progress_track[name]
|
||||||
pbar.setAttribute('value', x + '')
|
pbar.setAttribute('value', x + '')
|
||||||
progress.lastChild.textContent = str.format(_('Downloaded {0}, {1} left'), human_readable(x), human_readable(total - x))
|
progress.lastChild.textContent = _('Downloaded {0}, {1} left').format(human_readable(x), human_readable(total - x))
|
||||||
|
|
||||||
def on_stored(err):
|
def on_stored(err):
|
||||||
files_left.discard(this)
|
files_left.discard(this)
|
||||||
@ -184,7 +183,7 @@ class ReadUI:
|
|||||||
if len(files_left):
|
if len(files_left):
|
||||||
return
|
return
|
||||||
if failed_files.length:
|
if failed_files.length:
|
||||||
det = [str.format('<h4>{}</h4><div>{}</div><hr>', fname, err_html) for fname, err_html in failed_files].join('')
|
det = ['<h4>{}</h4><div>{}</div><hr>'.format(fname, err_html) for fname, err_html in failed_files].join('')
|
||||||
self.show_error(_('Could not download book'), _(
|
self.show_error(_('Could not download book'), _(
|
||||||
'Failed to download some book data, click "Show details" for more information'), det)
|
'Failed to download some book data, click "Show details" for more information'), det)
|
||||||
return
|
return
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import initialize # noqa: unused-import
|
||||||
from ajax import ajax
|
from ajax import ajax
|
||||||
from elementmaker import E
|
from elementmaker import E
|
||||||
from gettext import gettext as _, install
|
from gettext import gettext as _, install
|
||||||
|
@ -32,7 +32,7 @@ def parse_url_params(url=None, allow_multiple=False):
|
|||||||
return ans
|
return ans
|
||||||
pairs = q.replace(/\+/g, " ").split("&")
|
pairs = q.replace(/\+/g, " ").split("&")
|
||||||
for pair in pairs:
|
for pair in pairs:
|
||||||
key, val = str.partition(pair, '=')[::2]
|
key, val = pair.partition('=')[::2]
|
||||||
key, val = decodeURIComponent(key), decodeURIComponent(val)
|
key, val = decodeURIComponent(key), decodeURIComponent(val)
|
||||||
if allow_multiple:
|
if allow_multiple:
|
||||||
if not Object.prototype.hasOwnProperty.call(ans, key):
|
if not Object.prototype.hasOwnProperty.call(ans, key):
|
||||||
@ -64,7 +64,7 @@ def fmt_sidx(val, fmt='{:.2f}', use_roman=True):
|
|||||||
if use_roman:
|
if use_roman:
|
||||||
return roman(val)
|
return roman(val)
|
||||||
return int(val) + ''
|
return int(val) + ''
|
||||||
return str.format(fmt, float(val))
|
return fmt.format(float(val))
|
||||||
|
|
||||||
def human_readable(size, sep=' '):
|
def human_readable(size, sep=' '):
|
||||||
divisor, suffix = 1, "B"
|
divisor, suffix = 1, "B"
|
||||||
@ -73,10 +73,10 @@ def human_readable(size, sep=' '):
|
|||||||
divisor, suffix = (1 << (i * 10)), candidate
|
divisor, suffix = (1 << (i * 10)), candidate
|
||||||
break
|
break
|
||||||
size = (float(size)/divisor) + ''
|
size = (float(size)/divisor) + ''
|
||||||
pos = str.find(size, ".")
|
pos = size.find(".")
|
||||||
if pos > -1:
|
if pos > -1:
|
||||||
size = size[:pos + 2]
|
size = size[:pos + 2]
|
||||||
if str.endswith(size, '.0'):
|
if size.endswith('.0'):
|
||||||
size = size[:-2]
|
size = size[:-2]
|
||||||
return size + sep + suffix
|
return size + sep + suffix
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ BUTTON_VPADDING = '0.5ex'
|
|||||||
def create_button(text, icon=None, action=None, tooltip=None):
|
def create_button(text, icon=None, action=None, tooltip=None):
|
||||||
cls = ''
|
cls = ''
|
||||||
if icon:
|
if icon:
|
||||||
cls = str.format('fa fa-{} fa-lg', icon)
|
cls = 'fa fa-{} fa-lg'.format(icon)
|
||||||
text = '\xa0' + text
|
text = '\xa0' + text
|
||||||
ans = E.button(E.i(class_=cls), text, class_='calibre-push-button', type='button', title=tooltip or '')
|
ans = E.button(E.i(class_=cls), text, class_='calibre-push-button', type='button', title=tooltip or '')
|
||||||
if action is not None:
|
if action is not None:
|
||||||
@ -20,7 +20,7 @@ def create_button(text, icon=None, action=None, tooltip=None):
|
|||||||
|
|
||||||
create_button.style = build_rule('button.calibre-push-button',
|
create_button.style = build_rule('button.calibre-push-button',
|
||||||
border_radius='1em', background_clip='padding-box', background_color=get_color('button-start'),
|
border_radius='1em', background_clip='padding-box', background_color=get_color('button-start'),
|
||||||
background_image=str.format('linear-gradient(to bottom, {}, {})', get_color('button-start'), get_color('button-end')),
|
background_image='linear-gradient(to bottom, {}, {})'.format(get_color('button-start'), get_color('button-end')),
|
||||||
padding=BUTTON_VPADDING + ' 1em', color=get_color('button-text'), cursor='pointer', font_size='inherit'
|
padding=BUTTON_VPADDING + ' 1em', color=get_color('button-text'), cursor='pointer', font_size='inherit'
|
||||||
)
|
)
|
||||||
create_button.style += build_rule('button.calibre-push-button:hover', transform='scale(1.2)')
|
create_button.style += build_rule('button.calibre-push-button:hover', transform='scale(1.2)')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user