mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Stanza integration: Show number of books available for each tag/series/author in the catalog view
This commit is contained in:
parent
c8d2b4468f
commit
cb214d0bb3
@ -1047,6 +1047,18 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
|||||||
return [ (i[0], i[1]) for i in \
|
return [ (i[0], i[1]) for i in \
|
||||||
self.conn.get('SELECT id, name FROM series')]
|
self.conn.get('SELECT id, name FROM series')]
|
||||||
|
|
||||||
|
def series_name(self, series_id):
|
||||||
|
return self.conn.get('SELECT name FROM series WHERE id=%d'%series_id,
|
||||||
|
all=False)
|
||||||
|
|
||||||
|
def author_name(self, author_id):
|
||||||
|
return self.conn.get('SELECT name FROM authors WHERE id=%d'%author_id,
|
||||||
|
all=False)
|
||||||
|
|
||||||
|
def tag_name(self, tag_id):
|
||||||
|
return self.conn.get('SELECT name FROM tags WHERE id=%d'%tag_id,
|
||||||
|
all=False)
|
||||||
|
|
||||||
def all_authors(self):
|
def all_authors(self):
|
||||||
return [ (i[0], i[1]) for i in \
|
return [ (i[0], i[1]) for i in \
|
||||||
self.conn.get('SELECT id, name FROM authors')]
|
self.conn.get('SELECT id, name FROM authors')]
|
||||||
@ -1058,6 +1070,11 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
|||||||
def all_tags(self):
|
def all_tags(self):
|
||||||
return [i[0].strip() for i in self.conn.get('SELECT name FROM tags') if i[0].strip()]
|
return [i[0].strip() for i in self.conn.get('SELECT name FROM tags') if i[0].strip()]
|
||||||
|
|
||||||
|
def all_tags2(self):
|
||||||
|
return [ (i[0], i[1]) for i in \
|
||||||
|
self.conn.get('SELECT id, name FROM tags')]
|
||||||
|
|
||||||
|
|
||||||
def conversion_options(self, id, format):
|
def conversion_options(self, id, format):
|
||||||
data = self.conn.get('SELECT data FROM conversion_options WHERE book=? AND format=?', (id, format.upper()), all=False)
|
data = self.conn.get('SELECT data FROM conversion_options WHERE book=? AND format=?', (id, format.upper()), all=False)
|
||||||
if data:
|
if data:
|
||||||
|
@ -101,30 +101,13 @@ class LibraryServer(object):
|
|||||||
</entry>
|
</entry>
|
||||||
'''))
|
'''))
|
||||||
|
|
||||||
STANZA_AUTHOR_ENTRY=MarkupTemplate(textwrap.dedent('''\
|
STANZA_SUBCATALOG_ENTRY=MarkupTemplate(textwrap.dedent('''\
|
||||||
<entry xmlns:py="http://genshi.edgewall.org/">
|
<entry xmlns:py="http://genshi.edgewall.org/">
|
||||||
<title>${authors}</title>
|
<title>${title}</title>
|
||||||
<id>urn:calibre:${record[FM['id']]}</id>
|
<id>urn:calibre:${id}</id>
|
||||||
<updated>${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')}</updated>
|
<updated>${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')}</updated>
|
||||||
<link type="application/atom+xml" href="/stanza/?authorid=${record[FM['id']]}" />
|
<link type="application/atom+xml" href="/stanza/?${what}id=${id}" />
|
||||||
</entry>
|
<content type="text">${count} books</content>
|
||||||
'''))
|
|
||||||
|
|
||||||
STANZA_TAG_ENTRY=MarkupTemplate(textwrap.dedent('''\
|
|
||||||
<entry xmlns:py="http://genshi.edgewall.org/">
|
|
||||||
<title>${tags}</title>
|
|
||||||
<id>urn:calibre:${record[FM['id']]}</id>
|
|
||||||
<updated>${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')}</updated>
|
|
||||||
<link type="application/atom+xml" href="/stanza/?tagid=${record[FM['id']]}" />
|
|
||||||
</entry>
|
|
||||||
'''))
|
|
||||||
|
|
||||||
STANZA_SERIES_ENTRY=MarkupTemplate(textwrap.dedent('''\
|
|
||||||
<entry xmlns:py="http://genshi.edgewall.org/">
|
|
||||||
<title>${series}</title>
|
|
||||||
<id>urn:calibre:${record[FM['id']]}</id>
|
|
||||||
<updated>${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')}</updated>
|
|
||||||
<link type="application/atom+xml" href="/stanza/?seriesid=${record[FM['id']]}" />
|
|
||||||
</entry>
|
</entry>
|
||||||
'''))
|
'''))
|
||||||
|
|
||||||
@ -372,9 +355,39 @@ class LibraryServer(object):
|
|||||||
8:'Aug', 9:'Sep', 10:'Oct', 11:'Nov', 12:'Dec'}
|
8:'Aug', 9:'Sep', 10:'Oct', 11:'Nov', 12:'Dec'}
|
||||||
return lm.replace('month', month[updated.month])
|
return lm.replace('month', month[updated.month])
|
||||||
|
|
||||||
|
def get_matches(self, location, query):
|
||||||
|
base = self.db.data.get_matches(location, query)
|
||||||
|
epub = self.db.data.get_matches('format', 'epub')
|
||||||
|
pdb = self.db.data.get_matches('format', 'pdb')
|
||||||
|
return base.intersection(epub.union(pdb))
|
||||||
|
|
||||||
|
def stanza_sortby_subcategory(self, updated, sortby, offset):
|
||||||
|
what = sortby[2:]
|
||||||
|
if sortby == 'byseries':
|
||||||
|
data = self.db.all_series()
|
||||||
|
data = [(x[0], x[1], len(self.get_matches('series', x[1]))) for x in data]
|
||||||
|
elif sortby == 'byauthor':
|
||||||
|
data = self.db.all_authors()
|
||||||
|
data = [(x[0], x[1], len(self.get_matches('authors', x[1]))) for x in data]
|
||||||
|
elif sortby == 'bytag':
|
||||||
|
data = self.db.all_tags2()
|
||||||
|
data = [(x[0], x[1], len(self.get_matches('tags', x[1]))) for x in data]
|
||||||
|
data = [x for x in data if x[2] > 0]
|
||||||
|
data.sort(cmp=lambda x, y: cmp(x[1], y[1]))
|
||||||
|
entries = [self.STANZA_SUBCATALOG_ENTRY.generate(title=title, id=id,
|
||||||
|
what=what, updated=updated, count=c).render('xml').decode('utf-8') for id,
|
||||||
|
title, c in data]
|
||||||
|
entries = entries[offset:]
|
||||||
|
return self.STANZA.generate(subtitle='', data=entries, FM=FIELD_MAP,
|
||||||
|
updated=updated, id='urn:calibre:main').render('xml')
|
||||||
|
|
||||||
|
def stanza_main(self, updated):
|
||||||
|
return self.STANZA_MAIN.generate(subtitle='', data=[], FM=FIELD_MAP,
|
||||||
|
updated=updated, id='urn:calibre:main').render('xml')
|
||||||
|
|
||||||
@expose
|
@expose
|
||||||
def stanza(self, search=None, sortby=None, authorid=None, tagid=None, seriesid=None):
|
def stanza(self, search=None, sortby=None, authorid=None, tagid=None,
|
||||||
|
seriesid=None, offset=0):
|
||||||
'Feeds to read calibre books on a ipod with stanza.'
|
'Feeds to read calibre books on a ipod with stanza.'
|
||||||
books = []
|
books = []
|
||||||
updated = self.db.last_modified()
|
updated = self.db.last_modified()
|
||||||
@ -382,38 +395,34 @@ class LibraryServer(object):
|
|||||||
cherrypy.response.headers['Content-Type'] = 'text/xml'
|
cherrypy.response.headers['Content-Type'] = 'text/xml'
|
||||||
# Main feed
|
# Main feed
|
||||||
if not sortby and not search and not authorid and not tagid and not seriesid:
|
if not sortby and not search and not authorid and not tagid and not seriesid:
|
||||||
return self.STANZA_MAIN.generate(subtitle='', data=books, FM=FIELD_MAP,
|
return self.stanza_main(updated)
|
||||||
updated=updated, id='urn:calibre:main').render('xml')
|
if sortby in ('byseries', 'byauthor', 'bytag'):
|
||||||
# Sub-feed
|
return self.stanza_sortby_subcategory(updated, sortby, offset)
|
||||||
|
|
||||||
|
# Get matching ids
|
||||||
if authorid:
|
if authorid:
|
||||||
authorid=int(authorid)
|
authorid=int(authorid)
|
||||||
au = self.db.authors(authorid, index_is_id=True)
|
au = self.db.author_name(authorid)
|
||||||
ids = self.db.data.get_matches('authors', au)
|
ids = self.get_matches('authors', au)
|
||||||
elif tagid:
|
elif tagid:
|
||||||
tagid=int(tagid)
|
tagid=int(tagid)
|
||||||
ta = self.db.tags(tagid, index_is_id=True)
|
ta = self.db.tag_name(tagid)
|
||||||
ids = self.db.data.get_matches('tags', ta)
|
ids = self.get_matches('tags', ta)
|
||||||
elif seriesid:
|
elif seriesid:
|
||||||
seriesid=int(seriesid)
|
seriesid=int(seriesid)
|
||||||
se = self.db.series(seriesid, index_is_id=True)
|
se = self.db.series_name(seriesid)
|
||||||
ids = self.db.data.get_matches('series', se)
|
ids = self.get_matches('series', se)
|
||||||
else:
|
else:
|
||||||
ids = self.db.data.parse(search) if search and search.strip() else self.db.data.universal_set()
|
ids = self.db.data.parse(search) if search and search.strip() else self.db.data.universal_set()
|
||||||
record_list = list(iter(self.db))
|
record_list = list(iter(self.db))
|
||||||
|
|
||||||
# Sort the record list
|
# Sort the record list
|
||||||
if sortby == "byauthor":
|
if sortby == "bytitle" or authorid or tagid:
|
||||||
record_list.sort(lambda x, y: cmp(x[FIELD_MAP['author_sort']], y[FIELD_MAP['author_sort']]))
|
|
||||||
elif sortby == "bytag":
|
|
||||||
record_list.sort(lambda x, y: cmp(x[FIELD_MAP['tags']], y[FIELD_MAP['tags']]))
|
|
||||||
elif sortby == "byseries":
|
|
||||||
record_list.sort(lambda x, y: cmp(x[FIELD_MAP['series']], y[FIELD_MAP['series']]))
|
|
||||||
elif sortby == "bytitle" or authorid or tagid:
|
|
||||||
record_list.sort(lambda x, y: cmp(title_sort(x[FIELD_MAP['title']]),
|
record_list.sort(lambda x, y: cmp(title_sort(x[FIELD_MAP['title']]),
|
||||||
title_sort(y[FIELD_MAP['title']])))
|
title_sort(y[FIELD_MAP['title']])))
|
||||||
elif seriesid:
|
elif seriesid:
|
||||||
record_list.sort(lambda x, y: cmp(x[FIELD_MAP['series_index']], y[FIELD_MAP['series_index']]))
|
record_list.sort(lambda x, y: cmp(x[FIELD_MAP['series_index']], y[FIELD_MAP['series_index']]))
|
||||||
else:
|
else: # Sort by date
|
||||||
record_list = reversed(record_list)
|
record_list = reversed(record_list)
|
||||||
|
|
||||||
|
|
||||||
@ -460,33 +469,14 @@ class LibraryServer(object):
|
|||||||
authors=authors,
|
authors=authors,
|
||||||
tags=tags,
|
tags=tags,
|
||||||
series=series,
|
series=series,
|
||||||
FM=FIELD_MAP
|
FM=FIELD_MAP,
|
||||||
|
extra='\n'.join(extra),
|
||||||
|
mimetype=mimetype,
|
||||||
|
fmt=fmt,
|
||||||
|
timestamp=strftime('%Y-%m-%dT%H:%M:%S+00:00', record[5])
|
||||||
)
|
)
|
||||||
if sortby == "byauthor":
|
books.append(self.STANZA_ENTRY.generate(**data)\
|
||||||
if authors and authors not in author_list:
|
.render('xml').decode('utf8'))
|
||||||
author_list.append(authors)
|
|
||||||
books.append(self.STANZA_AUTHOR_ENTRY.generate(**data)\
|
|
||||||
.render('xml').decode('utf8'))
|
|
||||||
|
|
||||||
elif sortby == "bytag":
|
|
||||||
if tags and tags not in tag_list:
|
|
||||||
tag_list.append(tags)
|
|
||||||
books.append(self.STANZA_TAG_ENTRY.generate(**data)\
|
|
||||||
.render('xml').decode('utf8'))
|
|
||||||
|
|
||||||
elif sortby == "byseries":
|
|
||||||
if series and series not in series_list:
|
|
||||||
series_list.append(series)
|
|
||||||
books.append(self.STANZA_SERIES_ENTRY.generate(**data)\
|
|
||||||
.render('xml').decode('utf8'))
|
|
||||||
|
|
||||||
else: # An actual book list
|
|
||||||
data['extra'] = ''.join(extra)
|
|
||||||
data['mimetype'] = mimetype
|
|
||||||
data['fmt'] = fmt
|
|
||||||
data['timestamp'] = strftime('%Y-%m-%dT%H:%M:%S+00:00', record[5])
|
|
||||||
books.append(self.STANZA_ENTRY.generate(**data)\
|
|
||||||
.render('xml').decode('utf8'))
|
|
||||||
|
|
||||||
return self.STANZA.generate(subtitle='', data=books, FM=FIELD_MAP,
|
return self.STANZA.generate(subtitle='', data=books, FM=FIELD_MAP,
|
||||||
updated=updated, id='urn:calibre:main').render('xml')
|
updated=updated, id='urn:calibre:main').render('xml')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user