mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Template language: New function user_categories() to return the list of User Categories for a given book (only works in the GUI).
Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
commit
cbbfdee79c
@ -1901,6 +1901,41 @@ class Cache(object):
|
|||||||
ans[book].append(lib)
|
ans[book].append(lib)
|
||||||
return {k:tuple(sorted(v, key=sort_key)) for k, v in ans.iteritems()}
|
return {k:tuple(sorted(v, key=sort_key)) for k, v in ans.iteritems()}
|
||||||
|
|
||||||
|
@read_api
|
||||||
|
def user_categories_for_books(self, book_ids, proxy_metadata_map=None):
|
||||||
|
''' Return the user categories for the specified books.
|
||||||
|
proxy_metadata_map is optional and is useful for a performance boost,
|
||||||
|
in contexts where a ProxyMetadata object for the books already exists.
|
||||||
|
It should be a mapping of book_ids to their corresponding ProxyMetadata
|
||||||
|
objects.
|
||||||
|
'''
|
||||||
|
user_cats = self.backend.prefs['user_categories']
|
||||||
|
pmm = proxy_metadata_map or {}
|
||||||
|
ans = {}
|
||||||
|
|
||||||
|
for book_id in book_ids:
|
||||||
|
user_cat_vals = ans[book_id] = {}
|
||||||
|
for ucat, categories in user_cats.iteritems():
|
||||||
|
user_cat_vals[ucat] = res = []
|
||||||
|
proxy_metadata = pmm.get(book_id) or self._get_proxy_metadata(book_id)
|
||||||
|
for name, cat, ign in categories:
|
||||||
|
try:
|
||||||
|
field_obj = self.fields[cat]
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if field_obj.is_composite:
|
||||||
|
v = field_obj.get_value_with_cache(book_id, lambda x:proxy_metadata)
|
||||||
|
else:
|
||||||
|
v = self._fast_field_for(field_obj, book_id)
|
||||||
|
|
||||||
|
if isinstance(v, (list, tuple)):
|
||||||
|
if name in v:
|
||||||
|
res.append([name, cat])
|
||||||
|
elif name == v:
|
||||||
|
res.append([name, cat])
|
||||||
|
return ans
|
||||||
|
|
||||||
@write_api
|
@write_api
|
||||||
def embed_metadata(self, book_ids, only_fmts=None, report_error=None, report_progress=None):
|
def embed_metadata(self, book_ids, only_fmts=None, report_error=None, report_progress=None):
|
||||||
''' Update metadata in all formats of the specified book_ids to current metadata in the database. '''
|
''' Update metadata in all formats of the specified book_ids to current metadata in the database. '''
|
||||||
|
@ -241,6 +241,16 @@ def virtual_libraries_getter(dbref, book_id, cache):
|
|||||||
ret = cache['virtual_libraries'] = ', '.join(vls)
|
ret = cache['virtual_libraries'] = ', '.join(vls)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def user_categories_getter(proxy_metadata):
|
||||||
|
cache = ga(proxy_metadata, '_cache')
|
||||||
|
try:
|
||||||
|
return cache['user_categories']
|
||||||
|
except KeyError:
|
||||||
|
db = ga(proxy_metadata, '_db')()
|
||||||
|
book_id = ga(proxy_metadata, '_book_id')
|
||||||
|
ret = cache['user_categories'] = db.user_categories_for_books((book_id,), {book_id:proxy_metadata})[book_id]
|
||||||
|
return ret
|
||||||
|
|
||||||
getters = {
|
getters = {
|
||||||
'title':simple_getter('title', _('Unknown')),
|
'title':simple_getter('title', _('Unknown')),
|
||||||
'title_sort':simple_getter('sort', _('Unknown')),
|
'title_sort':simple_getter('sort', _('Unknown')),
|
||||||
@ -283,7 +293,7 @@ class ProxyMetadata(Metadata):
|
|||||||
sa(self, 'formatter', SafeFormat() if formatter is None else formatter)
|
sa(self, 'formatter', SafeFormat() if formatter is None else formatter)
|
||||||
sa(self, '_db', weakref.ref(db))
|
sa(self, '_db', weakref.ref(db))
|
||||||
sa(self, '_book_id', book_id)
|
sa(self, '_book_id', book_id)
|
||||||
sa(self, '_cache', {'user_categories':{}, 'cover_data':(None,None), 'device_collections':[]})
|
sa(self, '_cache', {'cover_data':(None,None), 'device_collections':[]})
|
||||||
sa(self, '_user_metadata', db.field_metadata)
|
sa(self, '_user_metadata', db.field_metadata)
|
||||||
|
|
||||||
def __getattribute__(self, field):
|
def __getattribute__(self, field):
|
||||||
@ -291,6 +301,8 @@ class ProxyMetadata(Metadata):
|
|||||||
if getter is not None:
|
if getter is not None:
|
||||||
return getter(ga(self, '_db'), ga(self, '_book_id'), ga(self, '_cache'))
|
return getter(ga(self, '_db'), ga(self, '_book_id'), ga(self, '_cache'))
|
||||||
if field in SIMPLE_GET:
|
if field in SIMPLE_GET:
|
||||||
|
if field == 'user_categories':
|
||||||
|
return user_categories_getter(self)
|
||||||
return ga(self, '_cache').get(field, None)
|
return ga(self, '_cache').get(field, None)
|
||||||
try:
|
try:
|
||||||
return ga(self, field)
|
return ga(self, field)
|
||||||
|
@ -527,7 +527,7 @@ class ReadingTest(BaseTest):
|
|||||||
from calibre.ebooks.metadata.book.base import STANDARD_METADATA_FIELDS
|
from calibre.ebooks.metadata.book.base import STANDARD_METADATA_FIELDS
|
||||||
cache = self.init_cache()
|
cache = self.init_cache()
|
||||||
for book_id in cache.all_book_ids():
|
for book_id in cache.all_book_ids():
|
||||||
mi = cache.get_metadata(book_id, get_user_categories=False)
|
mi = cache.get_metadata(book_id, get_user_categories=True)
|
||||||
pmi = cache.get_proxy_metadata(book_id)
|
pmi = cache.get_proxy_metadata(book_id)
|
||||||
self.assertSetEqual(set(mi.custom_field_keys()), set(pmi.custom_field_keys()))
|
self.assertSetEqual(set(mi.custom_field_keys()), set(pmi.custom_field_keys()))
|
||||||
|
|
||||||
|
@ -1397,6 +1397,23 @@ class BuiltinVirtualLibraries(BuiltinFormatterFunction):
|
|||||||
return mi._proxy_metadata.virtual_libraries
|
return mi._proxy_metadata.virtual_libraries
|
||||||
return _('This function can be used only in the GUI')
|
return _('This function can be used only in the GUI')
|
||||||
|
|
||||||
|
class BuiltinUserCategories(BuiltinFormatterFunction):
|
||||||
|
name = 'user_categories'
|
||||||
|
arg_count = 0
|
||||||
|
category = 'Get values from metadata'
|
||||||
|
__doc__ = doc = _('user_categories() -- return a comma-separated list of '
|
||||||
|
'the user categories that contain this book. This function '
|
||||||
|
'works only in the GUI. If you want to use these values '
|
||||||
|
'in save-to-disk or send-to-device templates then you '
|
||||||
|
'must make a custom "Column built from other columns", use '
|
||||||
|
'the function in that column\'s template, and use that '
|
||||||
|
'column\'s value in your save/send templates')
|
||||||
|
|
||||||
|
def evaluate(self, formatter, kwargs, mi, locals_):
|
||||||
|
if hasattr(mi, '_proxy_metadata'):
|
||||||
|
return ', '.join(k for k, v in mi._proxy_metadata.user_categories.iteritems() if v)
|
||||||
|
return _('This function can be used only in the GUI')
|
||||||
|
|
||||||
class BuiltinTransliterate(BuiltinFormatterFunction):
|
class BuiltinTransliterate(BuiltinFormatterFunction):
|
||||||
name = 'transliterate'
|
name = 'transliterate'
|
||||||
arg_count = 1
|
arg_count = 1
|
||||||
@ -1480,7 +1497,7 @@ _formatter_builtins = [
|
|||||||
BuiltinSublist(),BuiltinSubstr(), BuiltinSubtract(), BuiltinSwapAroundComma(),
|
BuiltinSublist(),BuiltinSubstr(), BuiltinSubtract(), BuiltinSwapAroundComma(),
|
||||||
BuiltinSwitch(), BuiltinTemplate(), BuiltinTest(), BuiltinTitlecase(),
|
BuiltinSwitch(), BuiltinTemplate(), BuiltinTest(), BuiltinTitlecase(),
|
||||||
BuiltinToday(), BuiltinTransliterate(), BuiltinUppercase(),
|
BuiltinToday(), BuiltinTransliterate(), BuiltinUppercase(),
|
||||||
BuiltinVirtualLibraries()
|
BuiltinUserCategories(), BuiltinVirtualLibraries()
|
||||||
]
|
]
|
||||||
|
|
||||||
class FormatterUserFunction(FormatterFunction):
|
class FormatterUserFunction(FormatterFunction):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user