mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Stanza integration:Implement result pagination. Fixes #3412 (Add alphabetical sub directories to content server)
This commit is contained in:
parent
751d855af5
commit
aee3d6febb
@ -134,7 +134,7 @@ class Install(Develop):
|
||||
The default <prefix> is the prefix of your python installation.
|
||||
''')
|
||||
|
||||
sub_commands = ['build']
|
||||
sub_commands = ['build', 'gui']
|
||||
|
||||
def add_options(self, parser):
|
||||
parser.add_option('--prefix', help='Installation prefix')
|
||||
|
@ -432,6 +432,7 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
||||
self.port.setValue(opts.port)
|
||||
self.username.setText(opts.username)
|
||||
self.password.setText(opts.password if opts.password else '')
|
||||
self.opt_max_opds_items.setValue(opts.max_opds_items)
|
||||
self.auto_launch.setChecked(config['autolaunch_server'])
|
||||
self.systray_icon.setChecked(config['systray_icon'])
|
||||
self.sync_news.setChecked(config['upload_news_to_device'])
|
||||
@ -729,6 +730,7 @@ class ConfigDialog(QDialog, Ui_Dialog):
|
||||
sc.set('password', unicode(self.password.text()).strip())
|
||||
sc.set('port', self.port.value())
|
||||
sc.set('max_cover', mcs)
|
||||
sc.set('max_opds_items', self.opt_max_opds_items.value())
|
||||
config['delete_news_from_library_on_upload'] = self.delete_news.isChecked()
|
||||
config['upload_news_to_device'] = self.sync_news.isChecked()
|
||||
config['search_as_you_type'] = self.search_as_you_type.isChecked()
|
||||
|
@ -790,13 +790,6 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="show_server_password">
|
||||
<property name="text">
|
||||
<string>&Show password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="max_cover_size">
|
||||
<property name="toolTip">
|
||||
<string>The maximum size (widthxheight) for displayed covers. Larger covers are resized. </string>
|
||||
@ -806,7 +799,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Max. &cover size:</string>
|
||||
@ -816,6 +809,33 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="show_server_password">
|
||||
<property name="text">
|
||||
<string>&Show password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Max. &OPDS items per query:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>opt_max_opds_items</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="opt_max_opds_items">
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -22,4 +22,7 @@ def server_config(defaults=None):
|
||||
help='Development mode. Server automatically restarts on file changes and serves code files (html, css, js) from the file system instead of calibre\'s resource system.')
|
||||
c.add_opt('max_cover', ['--max-cover'], default='600x800',
|
||||
help=_('The maximum size for displayed covers. Default is %default.'))
|
||||
c.add_opt('max_opds_items', ['--max-opds-items'], default=30,
|
||||
help=_('The maximum number of matches to return per OPDS query. '
|
||||
'This affects Stanza, WordPlayer, etc. integration.'))
|
||||
return c
|
||||
|
@ -118,6 +118,7 @@ class LibraryServer(object):
|
||||
<id>$id</id>
|
||||
<updated>${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')}</updated>
|
||||
<link rel="search" title="Search" type="application/atom+xml" href="/stanza/?search={searchTerms}"/>
|
||||
${Markup(next_link)}
|
||||
<author>
|
||||
<name>calibre</name>
|
||||
<uri>http://calibre.kovidgoyal.net</uri>
|
||||
@ -192,6 +193,7 @@ class LibraryServer(object):
|
||||
self.opts = opts
|
||||
self.max_cover_width, self.max_cover_height = \
|
||||
map(int, self.opts.max_cover.split('x'))
|
||||
self.max_stanza_items = opts.max_opds_items
|
||||
path = P('content_server')
|
||||
self.build_time = datetime.fromtimestamp(os.stat(path).st_mtime)
|
||||
self.default_cover = open(P('content_server/default_cover.jpg'), 'rb').read()
|
||||
@ -362,24 +364,35 @@ class LibraryServer(object):
|
||||
return base.intersection(epub.union(pdb))
|
||||
|
||||
def stanza_sortby_subcategory(self, updated, sortby, offset):
|
||||
what = sortby[2:]
|
||||
what, subtitle = 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]
|
||||
subtitle = 'Books by series'
|
||||
elif sortby == 'byauthor':
|
||||
data = self.db.all_authors()
|
||||
data = [(x[0], x[1], len(self.get_matches('authors', x[1]))) for x in data]
|
||||
subtitle = 'Books by author'
|
||||
elif sortby == 'bytag':
|
||||
data = self.db.all_tags2()
|
||||
data = [(x[0], x[1], len(self.get_matches('tags', x[1]))) for x in data]
|
||||
subtitle = 'Books by tag'
|
||||
data = [x for x in data if x[2] > 0]
|
||||
data.sort(cmp=lambda x, y: cmp(x[1], y[1]))
|
||||
next_offset = offset + self.max_stanza_items
|
||||
rdata = data[offset:next_offset]
|
||||
if next_offset >= len(data):
|
||||
next_offset = -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')
|
||||
title, c in rdata]
|
||||
next_link = ''
|
||||
if next_offset > -1:
|
||||
next_link = ('<link rel="next" title="Next" '
|
||||
'type="application/atom+xml" href="/stanza/?sortby=%s&offset=%d"/>\n'
|
||||
) % (sortby, next_offset)
|
||||
return self.STANZA.generate(subtitle=subtitle, data=entries, FM=FIELD_MAP,
|
||||
updated=updated, id='urn:calibre:main', next_link=next_link).render('xml')
|
||||
|
||||
def stanza_main(self, updated):
|
||||
return self.STANZA_MAIN.generate(subtitle='', data=[], FM=FIELD_MAP,
|
||||
@ -391,6 +404,7 @@ class LibraryServer(object):
|
||||
'Feeds to read calibre books on a ipod with stanza.'
|
||||
books = []
|
||||
updated = self.db.last_modified()
|
||||
offset = int(offset)
|
||||
cherrypy.response.headers['Last-Modified'] = self.last_modified(updated)
|
||||
cherrypy.response.headers['Content-Type'] = 'text/xml'
|
||||
# Main feed
|
||||
@ -426,15 +440,34 @@ class LibraryServer(object):
|
||||
record_list = reversed(record_list)
|
||||
|
||||
|
||||
fmts = FIELD_MAP['formats']
|
||||
pat = re.compile(r'EPUB|PDB', re.IGNORECASE)
|
||||
record_list = [x for x in record_list if x[0] in ids and
|
||||
pat.search(x[fmts] if x[fmts] else '') is not None]
|
||||
next_offset = offset + self.max_stanza_items
|
||||
nrecord_list = record_list[offset:next_offset]
|
||||
if next_offset >= len(record_list):
|
||||
next_offset = -1
|
||||
|
||||
next_link = ''
|
||||
if next_offset > -1:
|
||||
q = ['offset=%d'%next_offset]
|
||||
for x in ('search', 'sortby', 'authorid', 'tagid', 'seriesid'):
|
||||
val = locals()[x]
|
||||
if val is not None:
|
||||
val = prepare_string_for_xml(unicode(val), True)
|
||||
q.append('%s=%s'%(x, val))
|
||||
next_link = ('<link rel="next" title="Next" '
|
||||
'type="application/atom+xml" href="/stanza/?%s"/>\n'
|
||||
) % '&'.join(q)
|
||||
|
||||
author_list=[]
|
||||
tag_list=[]
|
||||
series_list=[]
|
||||
for record in record_list:
|
||||
if record[0] not in ids: continue
|
||||
|
||||
for record in nrecord_list:
|
||||
r = record[FIELD_MAP['formats']]
|
||||
r = r.upper() if r else ''
|
||||
if not ('EPUB' in r or 'PDB' in r):
|
||||
continue
|
||||
|
||||
z = record[FIELD_MAP['authors']]
|
||||
if not z:
|
||||
@ -479,7 +512,7 @@ class LibraryServer(object):
|
||||
.render('xml').decode('utf8'))
|
||||
|
||||
return self.STANZA.generate(subtitle='', data=books, FM=FIELD_MAP,
|
||||
updated=updated, id='urn:calibre:main').render('xml')
|
||||
next_link=next_link, updated=updated, id='urn:calibre:main').render('xml')
|
||||
|
||||
|
||||
@expose
|
||||
@ -533,7 +566,9 @@ class LibraryServer(object):
|
||||
cherrypy.request.headers.get('Want-OPDS-Catalog', 919) != 919 or \
|
||||
ua.startswith('Stanza')
|
||||
return self.stanza(search=kwargs.get('search', None), sortby=kwargs.get('sortby',None), authorid=kwargs.get('authorid',None),
|
||||
tagid=kwargs.get('tagid',None), seriesid=kwargs.get('seriesid',None)) if want_opds else self.static('index.html')
|
||||
tagid=kwargs.get('tagid',None),
|
||||
seriesid=kwargs.get('seriesid',None),
|
||||
offset=kwargs.get('offset', 0)) if want_opds else self.static('index.html')
|
||||
|
||||
|
||||
@expose
|
||||
|
Loading…
x
Reference in New Issue
Block a user