'
+__docformat__ = 'restructuredtext en'
+
+from uuid import uuid4
+
+from calibre.constants import __appname__, __version__
+from calibre import strftime, prepare_string_for_xml as xml
+
+SONY_METADATA = u'''\
+
+
+
+ {title}
+ {publisher}
+ {short_title}
+ {issue_date}
+ {language}
+
+
+
+
+
+'''
+
+SONY_ATOM = u'''\
+
+
+
+{short_title}
+{updated}
+{id}
+{entries}
+
+'''
+
+SONY_ATOM_SECTION = u'''\
+
+ {title}
+
+ {id}
+ {updated}
+ {desc}
+
+ newspaper/section
+
+
+'''
+
+SONY_ATOM_ENTRY = u'''\
+
+ {title}
+ {author}
+
+ {id}
+ {updated}
+ {desc}
+
+ {word_count}
+ newspaper/article
+
+
+'''
+
+def sony_metadata(oeb):
+ m = oeb.metadata
+ title = short_title = unicode(m.title[0])
+ publisher = __appname__ + ' ' + __version__
+ try:
+ pt = unicode(oeb.metadata.publication_type[0])
+ short_title = u':'.join(pt.split(':')[2:])
+ except:
+ pass
+
+ try:
+ date = unicode(m.date[0]).split('T')[0]
+ except:
+ date = strftime('%Y-%m-%d')
+ try:
+ language = unicode(m.language[0]).replace('_', '-')
+ except:
+ language = 'en'
+ short_title = xml(short_title, True)
+
+ metadata = SONY_METADATA.format(title=xml(title),
+ short_title=short_title,
+ publisher=xml(publisher), issue_date=xml(date),
+ language=xml(language))
+
+ updated = strftime('%Y-%m-%dT%H:%M:%SZ')
+
+ def cal_id(x):
+ for k, v in x.attrib.items():
+ if k.endswith('scheme') and v == 'uuid':
+ return True
+
+ try:
+ base_id = unicode(list(filter(cal_id, m.identifier))[0])
+ except:
+ base_id = str(uuid4())
+
+ entries = []
+ seen_titles = set([])
+ for i, section in enumerate(oeb.toc):
+ if not section.href:
+ continue
+ secid = 'section%d'%i
+ sectitle = section.title
+ if not sectitle:
+ sectitle = _('Unknown')
+ d = 1
+ bsectitle = sectitle
+ while sectitle in seen_titles:
+ sectitle = bsectitle + ' ' + str(d)
+ d += 1
+ seen_titles.add(sectitle)
+ sectitle = xml(sectitle, True)
+ secdesc = section.description
+ if not secdesc:
+ secdesc = ''
+ secdesc = xml(secdesc)
+ entries.append(SONY_ATOM_SECTION.format(title=sectitle,
+ href=section.href, id=xml(base_id)+'/'+secid,
+ short_title=short_title, desc=secdesc, updated=updated))
+
+ for j, article in enumerate(section):
+ if not article.href:
+ continue
+ atitle = article.title
+ btitle = atitle
+ d = 1
+ while atitle in seen_titles:
+ atitle = btitle + ' ' + str(d)
+ d += 1
+
+ auth = article.author if article.author else ''
+ desc = section.description
+ if not desc:
+ desc = ''
+ aid = 'article%d'%j
+
+ entries.append(SONY_ATOM_ENTRY.format(
+ title=xml(atitle),
+ author=xml(auth),
+ updated=updated,
+ desc=desc,
+ short_title=short_title,
+ section_title=sectitle,
+ href=article.href,
+ word_count=str(1),
+ id=xml(base_id)+'/'+secid+'/'+aid
+ ))
+
+ atom = SONY_ATOM.format(short_title=short_title,
+ entries='\n\n'.join(entries), updated=updated,
+ id=xml(base_id)).encode('utf-8')
+
+ return metadata, atom
+
diff --git a/src/calibre/ebooks/metadata/opf2.py b/src/calibre/ebooks/metadata/opf2.py
index 5c2477c3dc..62d57f2251 100644
--- a/src/calibre/ebooks/metadata/opf2.py
+++ b/src/calibre/ebooks/metadata/opf2.py
@@ -382,11 +382,13 @@ class Guide(ResourceCollection): # {{{
class MetadataField(object):
- def __init__(self, name, is_dc=True, formatter=None, none_is=None):
+ def __init__(self, name, is_dc=True, formatter=None, none_is=None,
+ renderer=lambda x: unicode(x)):
self.name = name
self.is_dc = is_dc
self.formatter = formatter
self.none_is = none_is
+ self.renderer = renderer
def __real_get__(self, obj, type=None):
ans = obj.get_metadata_element(self.name)
@@ -418,7 +420,7 @@ class MetadataField(object):
return
if elem is None:
elem = obj.create_metadata_element(self.name, is_dc=self.is_dc)
- obj.set_text(elem, unicode(val))
+ obj.set_text(elem, self.renderer(val))
def serialize_user_metadata(metadata_elem, all_user_metadata, tail='\n'+(' '*8)):
@@ -489,10 +491,11 @@ class OPF(object): # {{{
series = MetadataField('series', is_dc=False)
series_index = MetadataField('series_index', is_dc=False, formatter=float, none_is=1)
rating = MetadataField('rating', is_dc=False, formatter=int)
- pubdate = MetadataField('date', formatter=parse_date)
+ pubdate = MetadataField('date', formatter=parse_date,
+ renderer=isoformat)
publication_type = MetadataField('publication_type', is_dc=False)
timestamp = MetadataField('timestamp', is_dc=False,
- formatter=parse_date)
+ formatter=parse_date, renderer=isoformat)
def __init__(self, stream, basedir=os.getcwdu(), unquote_urls=True,
@@ -826,11 +829,10 @@ class OPF(object): # {{{
def fset(self, val):
matches = self.isbn_path(self.metadata)
- if val is None:
- if matches:
- for x in matches:
- x.getparent().remove(x)
- return
+ if not val:
+ for x in matches:
+ x.getparent().remove(x)
+ return
if not matches:
attrib = {'{%s}scheme'%self.NAMESPACES['opf']: 'ISBN'}
matches = [self.create_metadata_element('identifier',
@@ -987,11 +989,14 @@ class OPF(object): # {{{
def smart_update(self, mi, replace_metadata=False):
for attr in ('title', 'authors', 'author_sort', 'title_sort',
'publisher', 'series', 'series_index', 'rating',
- 'isbn', 'language', 'tags', 'category', 'comments',
+ 'isbn', 'tags', 'category', 'comments',
'pubdate'):
val = getattr(mi, attr, None)
if val is not None and val != [] and val != (None, None):
setattr(self, attr, val)
+ lang = getattr(mi, 'language', None)
+ if lang and lang != 'und':
+ self.language = lang
temp = self.to_book_metadata()
temp.smart_update(mi, replace_metadata=replace_metadata)
self._user_metadata_ = temp.get_all_user_metadata(True)
diff --git a/src/calibre/ebooks/mobi/output.py b/src/calibre/ebooks/mobi/output.py
index 49da18ea7b..4159c6dd40 100644
--- a/src/calibre/ebooks/mobi/output.py
+++ b/src/calibre/ebooks/mobi/output.py
@@ -42,11 +42,10 @@ class MOBIOutput(OutputFormatPlugin):
])
def check_for_periodical(self):
- if self.oeb.metadata.publication_type and \
- unicode(self.oeb.metadata.publication_type[0]).startswith('periodical:'):
- self.periodicalize_toc()
- self.check_for_masthead()
- self.opts.mobi_periodical = True
+ if self.is_periodical:
+ self.periodicalize_toc()
+ self.check_for_masthead()
+ self.opts.mobi_periodical = True
else:
self.opts.mobi_periodical = False
diff --git a/src/calibre/gui2/dialogs/fetch_metadata.py b/src/calibre/gui2/dialogs/fetch_metadata.py
index eb6edce75d..6ee9cd9a96 100644
--- a/src/calibre/gui2/dialogs/fetch_metadata.py
+++ b/src/calibre/gui2/dialogs/fetch_metadata.py
@@ -190,7 +190,8 @@ class FetchMetadata(QDialog, Ui_FetchMetadata):
if self.model.rowCount() < 1:
info_dialog(self, _('No metadata found'),
_('No metadata found, try adjusting the title and author '
- 'or the ISBN key.')).exec_()
+ 'and/or removing the ISBN.')).exec_()
+ self.reject()
return
self.matches.setModel(self.model)
diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py
index 2946985342..0286acc782 100644
--- a/src/calibre/gui2/library/models.py
+++ b/src/calibre/gui2/library/models.py
@@ -783,18 +783,22 @@ class BooksModel(QAbstractTableModel): # {{{
self.db.set_rating(id, val)
elif column == 'series':
val = val.strip()
- pat = re.compile(r'\[([.0-9]+)\]')
- match = pat.search(val)
- if match is not None:
- self.db.set_series_index(id, float(match.group(1)))
- val = pat.sub('', val).strip()
- elif val:
- if tweaks['series_index_auto_increment'] == 'next':
- ni = self.db.get_next_series_num_for(val)
- if ni != 1:
- self.db.set_series_index(id, ni)
- if val:
+ if not val:
self.db.set_series(id, val)
+ self.db.set_series_index(id, 1.0)
+ else:
+ pat = re.compile(r'\[([.0-9]+)\]')
+ match = pat.search(val)
+ if match is not None:
+ self.db.set_series_index(id, float(match.group(1)))
+ val = pat.sub('', val).strip()
+ elif val:
+ if tweaks['series_index_auto_increment'] == 'next':
+ ni = self.db.get_next_series_num_for(val)
+ if ni != 1:
+ self.db.set_series_index(id, ni)
+ if val:
+ self.db.set_series(id, val)
elif column == 'timestamp':
if val.isNull() or not val.isValid():
return False
diff --git a/src/calibre/library/server/base.py b/src/calibre/library/server/base.py
index 84e748a949..3a081fc427 100644
--- a/src/calibre/library/server/base.py
+++ b/src/calibre/library/server/base.py
@@ -148,6 +148,7 @@ class LibraryServer(ContentServer, MobileServer, XMLServer, OPDSServer, Cache,
cherrypy.engine.graceful()
def set_search_restriction(self, restriction):
+ self.search_restriction_name = restriction
if restriction:
self.search_restriction = 'search:"%s"'%restriction
else:
diff --git a/src/calibre/library/server/browse.py b/src/calibre/library/server/browse.py
index ea69ad77ef..ea86de4c1b 100644
--- a/src/calibre/library/server/browse.py
+++ b/src/calibre/library/server/browse.py
@@ -116,7 +116,10 @@ def render_rating(rating, container='span', prefix=None): # {{{
# }}}
-def get_category_items(category, items, db, datatype): # {{{
+def get_category_items(category, items, restriction, datatype): # {{{
+
+ if category == 'search':
+ items = [x for x in items if x.name != restriction]
def item(i):
templ = (u''
@@ -299,6 +302,7 @@ class BrowseServer(object):
category_meta = self.db.field_metadata
cats = [
(_('Newest'), 'newest', 'forward.png'),
+ (_('All books'), 'allbooks', 'book.png'),
]
def getter(x):
@@ -370,7 +374,8 @@ class BrowseServer(object):
if len(items) <= self.opts.max_opds_ungrouped_items:
script = 'false'
- items = get_category_items(category, items, self.db, datatype)
+ items = get_category_items(category, items,
+ self.search_restriction_name, datatype)
else:
getter = lambda x: unicode(getattr(x, 'sort', x.name))
starts = set([])
@@ -440,7 +445,8 @@ class BrowseServer(object):
entries.append(x)
sort = self.browse_sort_categories(entries, sort)
- entries = get_category_items(category, entries, self.db, datatype)
+ entries = get_category_items(category, entries,
+ self.search_restriction_name, datatype)
return json.dumps(entries, ensure_ascii=False)
@@ -451,6 +457,8 @@ class BrowseServer(object):
ans = self.browse_toplevel()
elif category == 'newest':
raise cherrypy.InternalRedirect('/browse/matches/newest/dummy')
+ elif category == 'allbooks':
+ raise cherrypy.InternalRedirect('/browse/matches/allbooks/dummy')
else:
ans = self.browse_category(category, category_sort)
@@ -478,16 +486,20 @@ class BrowseServer(object):
raise cherrypy.HTTPError(404, 'invalid category id: %r'%cid)
categories = self.categories_cache()
- if category not in categories and category != 'newest':
+ if category not in categories and \
+ category not in ('newest', 'allbooks'):
raise cherrypy.HTTPError(404, 'category not found')
fm = self.db.field_metadata
try:
category_name = fm[category]['name']
dt = fm[category]['datatype']
except:
- if category != 'newest':
+ if category not in ('newest', 'allbooks'):
raise
- category_name = _('Newest')
+ category_name = {
+ 'newest' : _('Newest'),
+ 'allbooks' : _('All books'),
+ }[category]
dt = None
hide_sort = 'true' if dt == 'series' else 'false'
@@ -498,8 +510,10 @@ class BrowseServer(object):
except:
raise cherrypy.HTTPError(404, 'Search: %r not understood'%which)
elif category == 'newest':
- ids = list(self.db.data.iterallids())
+ ids = self.search_cache('')
hide_sort = 'true'
+ elif category == 'allbooks':
+ ids = self.search_cache('')
else:
q = category
if q == 'news':
diff --git a/src/calibre/web/feeds/news.py b/src/calibre/web/feeds/news.py
index f3d77061c3..cb6bf30bcf 100644
--- a/src/calibre/web/feeds/news.py
+++ b/src/calibre/web/feeds/news.py
@@ -1104,7 +1104,7 @@ class BasicNewsRecipe(Recipe):
mi = MetaInformation(title, [__appname__])
mi.publisher = __appname__
mi.author_sort = __appname__
- mi.publication_type = 'periodical:'+self.publication_type
+ mi.publication_type = 'periodical:'+self.publication_type+':'+self.short_title()
mi.timestamp = nowf()
mi.comments = self.description
if not isinstance(mi.comments, unicode):