diff --git a/src/calibre/library/database.py b/src/calibre/library/database.py index d0d8b1aa61..3806679337 100644 --- a/src/calibre/library/database.py +++ b/src/calibre/library/database.py @@ -1047,6 +1047,18 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE; return [ (i[0], i[1]) for i in \ 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): return [ (i[0], i[1]) for i in \ 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): 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): data = self.conn.get('SELECT data FROM conversion_options WHERE book=? AND format=?', (id, format.upper()), all=False) if data: diff --git a/src/calibre/library/server.py b/src/calibre/library/server.py index 87e62da8c2..f4611a45e4 100644 --- a/src/calibre/library/server.py +++ b/src/calibre/library/server.py @@ -101,30 +101,13 @@ class LibraryServer(object): ''')) - STANZA_AUTHOR_ENTRY=MarkupTemplate(textwrap.dedent('''\ + STANZA_SUBCATALOG_ENTRY=MarkupTemplate(textwrap.dedent('''\ - ${authors} - urn:calibre:${record[FM['id']]} + ${title} + urn:calibre:${id} ${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')} - - - ''')) - - STANZA_TAG_ENTRY=MarkupTemplate(textwrap.dedent('''\ - - ${tags} - urn:calibre:${record[FM['id']]} - ${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')} - - - ''')) - - STANZA_SERIES_ENTRY=MarkupTemplate(textwrap.dedent('''\ - - ${series} - urn:calibre:${record[FM['id']]} - ${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')} - + + ${count} books ''')) @@ -372,9 +355,39 @@ class LibraryServer(object): 8:'Aug', 9:'Sep', 10:'Oct', 11:'Nov', 12:'Dec'} 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 - 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.' books = [] updated = self.db.last_modified() @@ -382,38 +395,34 @@ class LibraryServer(object): cherrypy.response.headers['Content-Type'] = 'text/xml' # Main feed 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, - updated=updated, id='urn:calibre:main').render('xml') - # Sub-feed + return self.stanza_main(updated) + if sortby in ('byseries', 'byauthor', 'bytag'): + return self.stanza_sortby_subcategory(updated, sortby, offset) + + # Get matching ids if authorid: authorid=int(authorid) - au = self.db.authors(authorid, index_is_id=True) - ids = self.db.data.get_matches('authors', au) + au = self.db.author_name(authorid) + ids = self.get_matches('authors', au) elif tagid: tagid=int(tagid) - ta = self.db.tags(tagid, index_is_id=True) - ids = self.db.data.get_matches('tags', ta) + ta = self.db.tag_name(tagid) + ids = self.get_matches('tags', ta) elif seriesid: seriesid=int(seriesid) - se = self.db.series(seriesid, index_is_id=True) - ids = self.db.data.get_matches('series', se) + se = self.db.series_name(seriesid) + ids = self.get_matches('series', se) else: ids = self.db.data.parse(search) if search and search.strip() else self.db.data.universal_set() record_list = list(iter(self.db)) # Sort the record list - if sortby == "byauthor": - 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: + if sortby == "bytitle" or authorid or tagid: record_list.sort(lambda x, y: cmp(title_sort(x[FIELD_MAP['title']]), title_sort(y[FIELD_MAP['title']]))) elif seriesid: 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) @@ -460,33 +469,14 @@ class LibraryServer(object): authors=authors, tags=tags, 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": - if authors and authors not in author_list: - 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')) + books.append(self.STANZA_ENTRY.generate(**data)\ + .render('xml').decode('utf8')) return self.STANZA.generate(subtitle='', data=books, FM=FIELD_MAP, updated=updated, id='urn:calibre:main').render('xml')