mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync to trunk.
This commit is contained in:
commit
930f6df87e
@ -36,7 +36,7 @@
|
|||||||
- title: "News downloads: When getting an article URL from a RSS feed, look first for an original article link. This speeds up the download of news services that use a syndication service like feedburner or pheedo to publish their RSS feeds."
|
- title: "News downloads: When getting an article URL from a RSS feed, look first for an original article link. This speeds up the download of news services that use a syndication service like feedburner or pheedo to publish their RSS feeds."
|
||||||
|
|
||||||
bug fixes:
|
bug fixes:
|
||||||
- "Windows device detection: Don't do expensive polling while waiting for device disconnect. This should fix the problems people have with their floppy drive being activated while an e-book reader is connected"
|
- title: "Windows device detection: Don't do expensive polling while waiting for device disconnect. This should fix the problems people have with their floppy drive being activated while an e-book reader is connected"
|
||||||
|
|
||||||
- title: "PML Input: Fix creation of metadata Table of Contents"
|
- title: "PML Input: Fix creation of metadata Table of Contents"
|
||||||
tickets: [5633]
|
tickets: [5633]
|
||||||
@ -84,7 +84,7 @@
|
|||||||
author: Darko Miletic
|
author: Darko Miletic
|
||||||
|
|
||||||
- title: Pajamas Media
|
- title: Pajamas Media
|
||||||
autor: Krittika Goyal
|
author: Krittika Goyal
|
||||||
|
|
||||||
- title: Algemeen Dagbla
|
- title: Algemeen Dagbla
|
||||||
author: kwetal
|
author: kwetal
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
body { background-color: white; }
|
||||||
|
|
||||||
p.title {
|
p.title {
|
||||||
margin-top:0em;
|
margin-top:0em;
|
||||||
margin-bottom:1em;
|
margin-bottom:1em;
|
||||||
|
BIN
resources/images/news/greensboro_news_and_record.png
Normal file
BIN
resources/images/news/greensboro_news_and_record.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 480 B |
BIN
resources/images/news/hotair.png
Normal file
BIN
resources/images/news/hotair.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 363 B |
BIN
resources/images/news/ionline_pt.png
Normal file
BIN
resources/images/news/ionline_pt.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 647 B |
BIN
resources/images/news/nationalreviewonline.png
Normal file
BIN
resources/images/news/nationalreviewonline.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 815 B |
BIN
resources/images/news/neowin.png
Normal file
BIN
resources/images/news/neowin.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
@ -98,6 +98,9 @@ class Barrons(BasicNewsRecipe):
|
|||||||
('Funds/Q&A', 'http://online.barrons.com/xml/rss/3_7519.xml'),
|
('Funds/Q&A', 'http://online.barrons.com/xml/rss/3_7519.xml'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def get_article_url(self, article):
|
||||||
|
return article.get('link', None)
|
||||||
|
|
||||||
|
|
||||||
def get_cover_url(self):
|
def get_cover_url(self):
|
||||||
cover_url = None
|
cover_url = None
|
||||||
|
@ -2,17 +2,37 @@
|
|||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
class CommonDreams(BasicNewsRecipe):
|
class CommonDreams(BasicNewsRecipe):
|
||||||
|
# Identify the recipe
|
||||||
|
|
||||||
title = u'Common Dreams'
|
title = u'Common Dreams'
|
||||||
description = u'Progressive news and views'
|
description = u'Progressive news and views'
|
||||||
__author__ = u'XanthanGum'
|
__author__ = u'XanthanGum'
|
||||||
language = 'en'
|
language = 'en'
|
||||||
|
|
||||||
|
# Format the text
|
||||||
|
|
||||||
|
extra_css = '''
|
||||||
|
body{font-family:verdana,arial,helvetica,geneva,sans-serif ;}
|
||||||
|
h1{font-size: xx-large;}
|
||||||
|
h2{font-size: large;}
|
||||||
|
'''
|
||||||
|
|
||||||
|
# Pick no article older than seven days and limit the number of articles per feed to 100
|
||||||
|
|
||||||
oldest_article = 7
|
oldest_article = 7
|
||||||
max_articles_per_feed = 100
|
max_articles_per_feed = 100
|
||||||
|
|
||||||
feeds = [
|
# Remove everything before the article
|
||||||
(u'Common Dreams Headlines',
|
|
||||||
u'http://www.commondreams.org/feed/headlines_rss'),
|
remove_tags_before = dict(name = 'div', attrs = {'id':'node-header'})
|
||||||
(u'Common Dreams Views', u'http://www.commondreams.org/feed/views_rss'),
|
|
||||||
(u'Common Dreams Newswire', u'http://www.commondreams.org/feed/newswire_rss')
|
# Remove everything after the article
|
||||||
]
|
|
||||||
|
remove_tags_after = dict(name = 'div', attrs = {'class':'copyright-info'})
|
||||||
|
|
||||||
|
# Identify the news feeds
|
||||||
|
|
||||||
|
feeds = [(u'Headlines', u'http://www.commondreams.org/feed/headlines_rss'),
|
||||||
|
(u'Further News Articles', u'http://www.commondreams.org/feed/further_rss'),
|
||||||
|
(u'Views', u'http://www.commondreams.org/feed/views_rss'),
|
||||||
|
(u'Progressive Newswire', u'http://www.commondreams.org/feed/newswire_rss')]
|
||||||
|
54
resources/recipes/greensboro_news_and_record.recipe
Normal file
54
resources/recipes/greensboro_news_and_record.recipe
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Walt Anthony <workshop.northpole at gmail.com>'
|
||||||
|
'''
|
||||||
|
www.news-record.com
|
||||||
|
'''
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class NewsandRecord(BasicNewsRecipe):
|
||||||
|
title = u'Greensboro News & Record'
|
||||||
|
description = "News from Greensboro, North Carolina"
|
||||||
|
__author__ = 'Walt Anthony'
|
||||||
|
publisher = 'News & Record and Landmark Media Enterprises, LLC'
|
||||||
|
category = 'news, USA'
|
||||||
|
oldest_article = 3 #days
|
||||||
|
max_articles_per_feed = 25
|
||||||
|
summary_length = 150
|
||||||
|
language = 'en'
|
||||||
|
encoding = 'utf-8'
|
||||||
|
remove_javascript = True
|
||||||
|
no_stylesheets = True
|
||||||
|
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : category
|
||||||
|
, 'publisher' : publisher
|
||||||
|
, 'language' : language
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
remove_tags_before = dict(name='h3', attrs={'class':'nrcTxt_headline'})
|
||||||
|
remove_tags_after = dict(name='div', attrs={'id':'nrcBlk_ContentBody'})
|
||||||
|
|
||||||
|
remove_tags = [
|
||||||
|
dict(name='iframe'),
|
||||||
|
dict(name=['notags','embed','object','link','img']),
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
('News', 'http://www.news-record.com/news/archive/feed'),
|
||||||
|
('Greensboro News', 'http://www.news-record.com/news/greensboro/feed'),
|
||||||
|
('Education', 'http://www.news-record.com/news/education/feed'),
|
||||||
|
('Government', 'http://www.news-record.com/news/government/feed'),
|
||||||
|
('College Sports', 'http://www.news-record.com/sports/college/feed'),
|
||||||
|
('Sports Extra', 'http://www.news-record.com/blog/sportsextra/feed'),
|
||||||
|
('Life', 'http://www.news-record.com/life/top/feed'),
|
||||||
|
('NASCAR', 'http://www.news-record.com/sports/nascar/top/feed'),
|
||||||
|
('Editorials', 'http://www.news-record.com/opinion/editorials/feed'),
|
||||||
|
('Letters to the Editor', 'http://www.news-record.com/opinion/letters/feed')
|
||||||
|
]
|
||||||
|
|
41
resources/recipes/hotair.recipe
Normal file
41
resources/recipes/hotair.recipe
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Walt Anthony <workshop.northpole at gmail.com>'
|
||||||
|
'''
|
||||||
|
www.hotair.com
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class hotair(BasicNewsRecipe):
|
||||||
|
title = u'Hot Air'
|
||||||
|
__author__ = 'Walt Anthony'
|
||||||
|
description = "The world's first, full-service conservative Internet broadcast network"
|
||||||
|
publisher = 'Hot Air'
|
||||||
|
category = 'news, politics, USA'
|
||||||
|
oldest_article = 3
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
summary_length = 150
|
||||||
|
language = 'en'
|
||||||
|
encoding = 'utf-8'
|
||||||
|
use_embedded_content = False
|
||||||
|
remove_javascript = True
|
||||||
|
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : category
|
||||||
|
, 'publisher' : publisher
|
||||||
|
, 'language' : language
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
keep_only_tags = [dict(name='div', attrs={'id':'page-post'})]
|
||||||
|
|
||||||
|
remove_tags = [dict(name=['iframe', 'small', 'embed', 'object','link','script','form'])]
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
('Hot Air', 'http://feeds.feedburner.com/hotair/main'),
|
||||||
|
('The Greenroom', 'http://feeds2.feedburner.com/hotair/greenroom')
|
||||||
|
]
|
58
resources/recipes/ionline_pt.recipe
Normal file
58
resources/recipes/ionline_pt.recipe
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
www.ionline.pt
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class IOnline_pt(BasicNewsRecipe):
|
||||||
|
title = 'ionline - Portugal'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'News from Portugal'
|
||||||
|
publisher = 'ionline.pt'
|
||||||
|
category = 'ionline, noticias, portugal, jornal, actualidade, benfica, bolsa, desporto, empresas, globo, europa, futebol, internacional, investir, lisboa, jogos, musica, videos, tempo, meteorologia, pais, politica, porto, sporting, fcporto, televisao, tv, opiniao, nacional, sociedade, crise, financeira, policia, crime, artes, cinema, cultura, madeleine, blog, ciencia, tecnologia, galerias, fotografia, fotos, famosos, emprego, imagens, teatro, news, mundial, governo, ps, psd, be, pcp, cds, pp, partidos'
|
||||||
|
oldest_article = 2
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
no_stylesheets = True
|
||||||
|
encoding = 'utf-8'
|
||||||
|
use_embedded_content = False
|
||||||
|
language = 'pt'
|
||||||
|
extra_css = ' .publish{font-style: italic; line-height: 1.2em; border-bottom: 1px dotted; padding: 5px 0} .entity{line-height: 1.2em} .overview{line-height:1.2em} '
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : category
|
||||||
|
, 'publisher' : publisher
|
||||||
|
, 'language' : language
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_only_tags = [
|
||||||
|
dict(name=['h5','h1'])
|
||||||
|
, dict(name='div', attrs={'class':['publish','overview','entity']})
|
||||||
|
]
|
||||||
|
|
||||||
|
remove_tags = [
|
||||||
|
dict(name=['object','embed','iframe'])
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
(u'Portugal' , u'http://www.ionline.pt/rss/portugal.xml' )
|
||||||
|
,(u'Mundo' , u'http://www.ionline.pt/rss/mundo.xml' )
|
||||||
|
,(u'Dinheiro' , u'http://www.ionline.pt/rss/dinheiro.xml' )
|
||||||
|
,(u'Desporto' , u'http://www.ionline.pt/rss/desporto.xml' )
|
||||||
|
,(u'Boa Vida' , u'http://www.ionline.pt/rss/boavida.xml' )
|
||||||
|
,(u'iReporter', u'http://www.ionline.pt/rss/ireporter.xml')
|
||||||
|
,(u'iBloges' , u'http://www.ionline.pt/rss/iblogues.xml' )
|
||||||
|
,(u'Desporto' , u'http://www.ionline.pt/rss/desporto.xml' )
|
||||||
|
]
|
||||||
|
|
||||||
|
def print_version(self, url):
|
||||||
|
rest = url.rpartition('/')[2]
|
||||||
|
lmain = rest.partition('-')[0]
|
||||||
|
lurl = u'http://www.ionline.pt/interior/index.php?p=news-print&idNota=' + lmain
|
||||||
|
return lurl
|
||||||
|
|
||||||
|
|
50
resources/recipes/nationalreviewonline.recipe
Normal file
50
resources/recipes/nationalreviewonline.recipe
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Walt Anthony <workshop.northpole at gmail.com>'
|
||||||
|
'''
|
||||||
|
www.nationalreview.com
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class NRO(BasicNewsRecipe):
|
||||||
|
title = u'National Review Online'
|
||||||
|
__author__ = 'Walt Anthony'
|
||||||
|
description = "National Review is America's most widely read and influential magazine and web site for Republican/conservative news, commentary, and opinion."
|
||||||
|
publisher = 'National Review, Inc.'
|
||||||
|
category = 'news, politics, USA'
|
||||||
|
oldest_article = 3
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
summary_length = 150
|
||||||
|
language = 'en'
|
||||||
|
encoding = 'utf-8'
|
||||||
|
use_embedded_content = True
|
||||||
|
remove_javascript = True
|
||||||
|
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : category
|
||||||
|
, 'publisher' : publisher
|
||||||
|
, 'language' : language
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_tags = [
|
||||||
|
dict(name=['embed','object','iframe']),
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
|
||||||
|
(u'National Review', u'http://www.nationalreview.com/index.xml'),
|
||||||
|
(u'The Corner', u'http://corner.nationalreview.com/corner.xml'),
|
||||||
|
(u'The Agenda', u'http://agenda.nationalreview.com/agenda.xml'),
|
||||||
|
(u'Bench Memos', u'http://bench.nationalreview.com/bench.xml'),
|
||||||
|
(u'Campaign Spot', u'http://campaignspot.nationalreview.com/campaignspot.xml'),
|
||||||
|
(u'Critical Care', u'http://healthcare.nationalreview.com/healthcare.xml'),
|
||||||
|
(u'Doctor, Doctor', u'http://www.nationalreview.com/doctor/doctor.xml'),
|
||||||
|
(u"Kudlow's Money Politic$", u'http://kudlow.nationalreview.com/kudlow.xml'),
|
||||||
|
(u'Media Blog', u'http://media.nationalreview.com/media.xml'),
|
||||||
|
(u'Phi Beta Cons', u'http://phibetacons.nationalreview.com/phibetacons.xml'),
|
||||||
|
(u'Planet Gore', u'http://planetgore.nationalreview.com/planetgore.xml')
|
||||||
|
|
||||||
|
]
|
40
resources/recipes/neowin.recipe
Normal file
40
resources/recipes/neowin.recipe
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class Neowin(BasicNewsRecipe):
|
||||||
|
title = u'Neowin.net'
|
||||||
|
oldest_article = 5
|
||||||
|
language = 'en'
|
||||||
|
description = 'News from IT'
|
||||||
|
publisher = 'Neowin'
|
||||||
|
category = 'news, IT, Microsoft, Apple, hardware, software, games'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
no_stylesheets = True
|
||||||
|
encoding = 'utf8'
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'tags' : category
|
||||||
|
,'language' : language
|
||||||
|
,'comments' : description
|
||||||
|
,'publisher' : publisher
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_only_tags = [dict(name='div', attrs={'id':'article'})]
|
||||||
|
remove_tags_after = dict(name='div', attrs={'id':'tag-bar'})
|
||||||
|
|
||||||
|
remove_tags = [
|
||||||
|
dict(name=['base','object','link','iframe'])
|
||||||
|
,dict(name='div', attrs={'id':'tag-bar'})
|
||||||
|
]
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
(u'Software' , u'http://www.neowin.net/news/rss/software' )
|
||||||
|
,(u'Gaming' , u'http://www.neowin.net/news/rss/gaming' )
|
||||||
|
,(u'Microsoft', u'http://www.neowin.net/news/rss/microsoft')
|
||||||
|
,(u'Apple' , u'http://www.neowin.net/news/rss/apple' )
|
||||||
|
,(u'Editorial', u'http://www.neowin.net/news/rss/editorial')
|
||||||
|
]
|
||||||
|
def image_url_processor(cls, baseurl, url):
|
||||||
|
return url
|
||||||
|
|
@ -1,44 +1,105 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__docformat__ = 'restructuredtext en'
|
__copyright__ = '2010, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
www.wired.com
|
||||||
|
'''
|
||||||
|
|
||||||
|
import re
|
||||||
|
from calibre import strftime
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
class Wired(BasicNewsRecipe):
|
class Wired(BasicNewsRecipe):
|
||||||
|
title = 'Wired Magazine'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'Gaming news'
|
||||||
|
publisher = 'Conde Nast Digital'
|
||||||
|
category = 'news, games, IT, gadgets'
|
||||||
|
oldest_article = 32
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
no_stylesheets = True
|
||||||
|
encoding = 'utf-8'
|
||||||
|
use_embedded_content = False
|
||||||
|
language = 'en'
|
||||||
|
extra_css = ' body{font-family: sans-serif} .entryDescription li {display: inline; list-style-type: none} '
|
||||||
|
index = 'http://www.wired.com/magazine/'
|
||||||
|
|
||||||
title = 'Wired.com'
|
preprocess_regexps = [(re.compile(r'<meta name="Title".*<title>', re.DOTALL|re.IGNORECASE),lambda match: '<title>')]
|
||||||
__author__ = 'Kovid Goyal'
|
conversion_options = {
|
||||||
description = 'Technology news'
|
'comment' : description
|
||||||
timefmt = ' [%Y%b%d %H%M]'
|
, 'tags' : category
|
||||||
language = 'en'
|
, 'publisher' : publisher
|
||||||
|
, 'language' : language
|
||||||
|
}
|
||||||
|
|
||||||
no_stylesheets = True
|
keep_only_tags = [dict(name='div', attrs={'class':'post'})]
|
||||||
|
remove_tags_after = dict(name='div', attrs={'class':'tweetmeme_button'})
|
||||||
|
remove_tags = [
|
||||||
|
dict(name=['object','embed','iframe','link'])
|
||||||
|
,dict(name='div', attrs={'class':['podcast_storyboard','tweetmeme_button']})
|
||||||
|
]
|
||||||
|
|
||||||
remove_tags_before = dict(name='div', id='content')
|
|
||||||
remove_tags = [dict(id=['social_tools', 'outerWrapper', 'sidebar',
|
|
||||||
'footer', 'advertisement', 'blog_subscription_unit',
|
|
||||||
'brightcove_component']),
|
|
||||||
{'class':'entryActions'},
|
|
||||||
dict(name=['noscript', 'script'])]
|
|
||||||
|
|
||||||
feeds = [
|
#feeds = [(u'Articles' , u'http://www.wired.com/magazine/feed/' )]
|
||||||
('Top News', 'http://feeds.wired.com/wired/index'),
|
|
||||||
('Culture', 'http://feeds.wired.com/wired/culture'),
|
def parse_index(self):
|
||||||
('Software', 'http://feeds.wired.com/wired/software'),
|
totalfeeds = []
|
||||||
('Mac', 'http://feeds.feedburner.com/cultofmac/bFow'),
|
|
||||||
('Gadgets', 'http://feeds.wired.com/wired/gadgets'),
|
soup = self.index_to_soup(self.index)
|
||||||
('Cars', 'http://feeds.wired.com/wired/cars'),
|
features = soup.find('div',attrs={'id':'my-glider'})
|
||||||
('Entertainment', 'http://feeds.wired.com/wired/entertainment'),
|
if features:
|
||||||
('Gaming', 'http://feeds.wired.com/wired/gaming'),
|
farticles = []
|
||||||
('Science', 'http://feeds.wired.com/wired/science'),
|
for item in features.findAll('div',attrs={'class':'section'}):
|
||||||
('Med Tech', 'http://feeds.wired.com/wired/medtech'),
|
divurl = item.find('div',attrs={'class':'feature-header'})
|
||||||
('Politics', 'http://feeds.wired.com/wired/politics'),
|
divdesc = item.find('div',attrs={'class':'feature-text'})
|
||||||
('Tech Biz', 'http://feeds.wired.com/wired/techbiz'),
|
url = 'http://www.wired.com' + divurl.a['href']
|
||||||
('Commentary', 'http://feeds.wired.com/wired/commentary'),
|
title = self.tag_to_string(divurl.a)
|
||||||
]
|
description = self.tag_to_string(divdesc)
|
||||||
|
date = strftime(self.timefmt)
|
||||||
|
farticles.append({
|
||||||
|
'title' :title
|
||||||
|
,'date' :date
|
||||||
|
,'url' :url
|
||||||
|
,'description':description
|
||||||
|
})
|
||||||
|
totalfeeds.append(('Featured Articles', farticles))
|
||||||
|
#department feeds
|
||||||
|
departments = ['rants','start','test','play','found']
|
||||||
|
dept = soup.find('div',attrs={'id':'magazine-departments'})
|
||||||
|
if dept:
|
||||||
|
for ditem in departments:
|
||||||
|
darticles = []
|
||||||
|
department = dept.find('div',attrs={'id':'department-'+ditem})
|
||||||
|
if department:
|
||||||
|
for item in department.findAll('div'):
|
||||||
|
description = ''
|
||||||
|
feed_link = item.find('a')
|
||||||
|
if feed_link and feed_link.has_key('href'):
|
||||||
|
url = feed_link['href']
|
||||||
|
title = self.tag_to_string(feed_link)
|
||||||
|
date = strftime(self.timefmt)
|
||||||
|
darticles.append({
|
||||||
|
'title' :title
|
||||||
|
,'date' :date
|
||||||
|
,'url' :url
|
||||||
|
,'description':description
|
||||||
|
})
|
||||||
|
totalfeeds.append((ditem.capitalize(), darticles))
|
||||||
|
return totalfeeds
|
||||||
|
|
||||||
|
def get_cover_url(self):
|
||||||
|
cover_url = None
|
||||||
|
soup = self.index_to_soup(self.index)
|
||||||
|
cover_item = soup.find('div',attrs={'class':'spread-image'})
|
||||||
|
if cover_item:
|
||||||
|
cover_url = 'http://www.wired.com' + cover_item.a.img['src']
|
||||||
|
return cover_url
|
||||||
|
|
||||||
def print_version(self, url):
|
def print_version(self, url):
|
||||||
return url.replace('http://www.wired.com/', 'http://www.wired.com/print/')
|
return url.rstrip('/') + '/all/1'
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
for item in soup.findAll(style=True):
|
||||||
|
del item['style']
|
||||||
|
return soup
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
__appname__ = 'calibre'
|
__appname__ = 'calibre'
|
||||||
__version__ = '0.6.34'
|
__version__ = '0.6.35'
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
@ -255,9 +255,16 @@ class CatalogPlugin(Plugin):
|
|||||||
|
|
||||||
def search_sort_db(self, db, opts):
|
def search_sort_db(self, db, opts):
|
||||||
|
|
||||||
# If declared, --ids overrides any declared search criteria
|
'''
|
||||||
if not opts.ids and opts.search_text:
|
# Don't add Catalogs to the generated Catalogs
|
||||||
db.search(opts.search_text)
|
cat = _('Catalog')
|
||||||
|
if opts.search_text:
|
||||||
|
opts.search_text += ' not tag:'+cat
|
||||||
|
else:
|
||||||
|
opts.search_text = 'not tag:'+cat
|
||||||
|
'''
|
||||||
|
|
||||||
|
db.search(opts.search_text)
|
||||||
|
|
||||||
if opts.sort_by:
|
if opts.sort_by:
|
||||||
# 2nd arg = ascending
|
# 2nd arg = ascending
|
||||||
|
@ -268,7 +268,8 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
# remove <img> tags with empty src elements
|
# remove <img> tags with empty src elements
|
||||||
bad = []
|
bad = []
|
||||||
for x in XPath('//h:img')(body):
|
for x in XPath('//h:img')(body):
|
||||||
if not x.get('src', '').strip():
|
src = x.get('src', '').strip()
|
||||||
|
if src in ('', '#'):
|
||||||
bad.append(x)
|
bad.append(x)
|
||||||
for img in bad:
|
for img in bad:
|
||||||
img.getparent().remove(img)
|
img.getparent().remove(img)
|
||||||
|
@ -619,7 +619,6 @@ class MobiWriter(object):
|
|||||||
self._oeb.log.warning('_generate_indexed_navpoints: Failed to generate index')
|
self._oeb.log.warning('_generate_indexed_navpoints: Failed to generate index')
|
||||||
# Zero out self._HTMLRecords, return False
|
# Zero out self._HTMLRecords, return False
|
||||||
self._HTMLRecords = []
|
self._HTMLRecords = []
|
||||||
#last_name = None
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
previousOffset = offset
|
previousOffset = offset
|
||||||
|
@ -18,38 +18,11 @@ class Font(object):
|
|||||||
self.color = spec.get('color')
|
self.color = spec.get('color')
|
||||||
self.family = spec.get('family')
|
self.family = spec.get('family')
|
||||||
|
|
||||||
class Column(object):
|
class Element(object):
|
||||||
|
|
||||||
# A column contains an element is the element bulges out to
|
|
||||||
# the left or the right by at most HFUZZ*col width.
|
|
||||||
HFUZZ = 0.2
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.left = self.right = self.top = self.bottom = 0
|
self.starts_block = None
|
||||||
self.width = self.height = 0
|
self.block_style = None
|
||||||
self.elements = []
|
|
||||||
|
|
||||||
def add(self, elem):
|
|
||||||
if elem in self.elements: return
|
|
||||||
self.elements.append(elem)
|
|
||||||
self.elements.sort(cmp=lambda x,y:cmp(x.bottom,y.bottom))
|
|
||||||
self.top = self.elements[0].top
|
|
||||||
self.bottom = self.elements[-1].bottom
|
|
||||||
self.left, self.right = sys.maxint, 0
|
|
||||||
for x in self:
|
|
||||||
self.left = min(self.left, x.left)
|
|
||||||
self.right = max(self.right, x.right)
|
|
||||||
self.width, self.height = self.right-self.left, self.bottom-self.top
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
for x in self.elements:
|
|
||||||
yield x
|
|
||||||
|
|
||||||
def contains(self, elem):
|
|
||||||
return elem.left > self.left - self.HFUZZ*self.width and \
|
|
||||||
elem.right < self.right + self.HFUZZ*self.width
|
|
||||||
|
|
||||||
class Element(object):
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.id == other.id
|
return self.id == other.id
|
||||||
@ -60,6 +33,7 @@ class Element(object):
|
|||||||
class Image(Element):
|
class Image(Element):
|
||||||
|
|
||||||
def __init__(self, img, opts, log, idc):
|
def __init__(self, img, opts, log, idc):
|
||||||
|
Element.__init__(self)
|
||||||
self.opts, self.log = opts, log
|
self.opts, self.log = opts, log
|
||||||
self.id = idc.next()
|
self.id = idc.next()
|
||||||
self.top, self.left, self.width, self.height, self.iwidth, self.iheight = \
|
self.top, self.left, self.width, self.height, self.iwidth, self.iheight = \
|
||||||
@ -71,6 +45,7 @@ class Image(Element):
|
|||||||
class Text(Element):
|
class Text(Element):
|
||||||
|
|
||||||
def __init__(self, text, font_map, opts, log, idc):
|
def __init__(self, text, font_map, opts, log, idc):
|
||||||
|
Element.__init__(self)
|
||||||
self.id = idc.next()
|
self.id = idc.next()
|
||||||
self.opts, self.log = opts, log
|
self.opts, self.log = opts, log
|
||||||
self.font_map = font_map
|
self.font_map = font_map
|
||||||
@ -140,20 +115,78 @@ class Interval(object):
|
|||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash('(%f,%f)'%self.left, self.right)
|
return hash('(%f,%f)'%self.left, self.right)
|
||||||
|
|
||||||
|
class Column(object):
|
||||||
|
|
||||||
|
# A column contains an element is the element bulges out to
|
||||||
|
# the left or the right by at most HFUZZ*col width.
|
||||||
|
HFUZZ = 0.2
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.left = self.right = self.top = self.bottom = 0
|
||||||
|
self.width = self.height = 0
|
||||||
|
self.elements = []
|
||||||
|
self.average_line_separation = 0
|
||||||
|
|
||||||
|
def add(self, elem):
|
||||||
|
if elem in self.elements: return
|
||||||
|
self.elements.append(elem)
|
||||||
|
self.elements.sort(cmp=lambda x,y:cmp(x.bottom,y.bottom))
|
||||||
|
self.top = self.elements[0].top
|
||||||
|
self.bottom = self.elements[-1].bottom
|
||||||
|
self.left, self.right = sys.maxint, 0
|
||||||
|
for x in self:
|
||||||
|
self.left = min(self.left, x.left)
|
||||||
|
self.right = max(self.right, x.right)
|
||||||
|
self.width, self.height = self.right-self.left, self.bottom-self.top
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
for x in self.elements:
|
||||||
|
yield x
|
||||||
|
|
||||||
|
def contains(self, elem):
|
||||||
|
return elem.left > self.left - self.HFUZZ*self.width and \
|
||||||
|
elem.right < self.right + self.HFUZZ*self.width
|
||||||
|
|
||||||
|
def collect_stats(self):
|
||||||
|
if len(self.elements) > 1:
|
||||||
|
gaps = [self.elements[i+1].top - self.elements[i].bottom for i in
|
||||||
|
range(len(0, len(self.elements)-1))]
|
||||||
|
self.average_line_separation = sum(gaps)/len(gaps)
|
||||||
|
for i, elem in enumerate(self.elements):
|
||||||
|
left_margin = elem.left - self.left
|
||||||
|
elem.indent_fraction = left_margin/self.width
|
||||||
|
elem.width_fraction = elem.width/self.width
|
||||||
|
if i == 0:
|
||||||
|
elem.top_gap = None
|
||||||
|
else:
|
||||||
|
elem.top_gap = self.elements[i-1].bottom - elem.top
|
||||||
|
|
||||||
|
def previous_element(self, idx):
|
||||||
|
if idx == 0:
|
||||||
|
return None
|
||||||
|
return self.elements[idx-1]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Region(object):
|
class Region(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.columns = []
|
self.columns = []
|
||||||
self.top = self.bottom = self.left = self.right = self.width = self.height = 0
|
self.top = self.bottom = self.left = self.right = self.width = self.height = 0
|
||||||
|
|
||||||
def add_columns(self, columns):
|
def add(self, columns):
|
||||||
if not self.columns:
|
if not self.columns:
|
||||||
for x in sorted(columns, cmp=lambda x,y: cmp(x.left, y.left)):
|
for x in sorted(columns, cmp=lambda x,y: cmp(x.left, y.left)):
|
||||||
self.columns.append(x)
|
self.columns.append(x)
|
||||||
else:
|
else:
|
||||||
pass
|
for i in range(len(columns)):
|
||||||
|
for elem in columns[i]:
|
||||||
|
self.columns[i].add(elem)
|
||||||
|
|
||||||
def contains(self, columns):
|
def contains(self, columns):
|
||||||
|
# TODO: handle unbalanced columns
|
||||||
if not self.columns:
|
if not self.columns:
|
||||||
return True
|
return True
|
||||||
if len(columns) != len(self.columns):
|
if len(columns) != len(self.columns):
|
||||||
@ -168,6 +201,26 @@ class Region(object):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_empty(self):
|
||||||
|
return len(self.elements) == 0
|
||||||
|
|
||||||
|
def collect_stats(self):
|
||||||
|
for column in self.columns:
|
||||||
|
column.collect_stats()
|
||||||
|
self.average_line_separation = sum([x.average_line_separation for x in
|
||||||
|
self.columns])/float(len(self.columns))
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
for x in self.columns:
|
||||||
|
yield x
|
||||||
|
|
||||||
|
def linearize(self):
|
||||||
|
self.elements = []
|
||||||
|
for x in self.columns:
|
||||||
|
self.elements.extend(x)
|
||||||
|
|
||||||
|
|
||||||
class Page(object):
|
class Page(object):
|
||||||
|
|
||||||
# Fraction of a character width that two strings have to be apart,
|
# Fraction of a character width that two strings have to be apart,
|
||||||
@ -178,6 +231,8 @@ class Page(object):
|
|||||||
# for them to be considered to be part of the same text fragment
|
# for them to be considered to be part of the same text fragment
|
||||||
LINE_FACTOR = 0.4
|
LINE_FACTOR = 0.4
|
||||||
|
|
||||||
|
# Multiplies the average line height when determining row height
|
||||||
|
# of a particular element to detect columns.
|
||||||
YFUZZ = 1.5
|
YFUZZ = 1.5
|
||||||
|
|
||||||
|
|
||||||
@ -242,19 +297,25 @@ class Page(object):
|
|||||||
self.texts.remove(match)
|
self.texts.remove(match)
|
||||||
|
|
||||||
def first_pass(self):
|
def first_pass(self):
|
||||||
|
'Sort page into regions and columns'
|
||||||
self.regions = []
|
self.regions = []
|
||||||
if not self.elements:
|
if not self.elements:
|
||||||
return
|
return
|
||||||
for i, x in enumerate(self.elements):
|
for i, x in enumerate(self.elements):
|
||||||
x.idx = i
|
x.idx = i
|
||||||
self.current_region = None
|
current_region = Region()
|
||||||
processed = set([])
|
processed = set([])
|
||||||
for x in self.elements:
|
for x in self.elements:
|
||||||
if x in processed: continue
|
if x in processed: continue
|
||||||
elems = set(self.find_elements_in_row_of(x))
|
elems = set(self.find_elements_in_row_of(x))
|
||||||
columns = self.sort_into_columns(x, elems)
|
columns = self.sort_into_columns(x, elems)
|
||||||
processed.update(elems)
|
processed.update(elems)
|
||||||
columns
|
if not current_region.contains(columns):
|
||||||
|
self.regions.append(self.current_region)
|
||||||
|
current_region = Region()
|
||||||
|
current_region.add(columns)
|
||||||
|
if not self.current_region.is_empty():
|
||||||
|
self.regions.append(current_region)
|
||||||
|
|
||||||
def sort_into_columns(self, elem, neighbors):
|
def sort_into_columns(self, elem, neighbors):
|
||||||
columns = [Column()]
|
columns = [Column()]
|
||||||
@ -274,7 +335,7 @@ class Page(object):
|
|||||||
|
|
||||||
def find_elements_in_row_of(self, x):
|
def find_elements_in_row_of(self, x):
|
||||||
interval = Interval(x.top,
|
interval = Interval(x.top,
|
||||||
x.top + self.YFUZZ*(1+self.average_text_height))
|
x.top + self.YFUZZ*(self.average_text_height))
|
||||||
h_interval = Interval(x.left, x.right)
|
h_interval = Interval(x.left, x.right)
|
||||||
for y in self.elements[x.idx:x.idx+15]:
|
for y in self.elements[x.idx:x.idx+15]:
|
||||||
if y is not x:
|
if y is not x:
|
||||||
@ -285,6 +346,12 @@ class Page(object):
|
|||||||
x_interval.intersection(h_interval).width <= 0:
|
x_interval.intersection(h_interval).width <= 0:
|
||||||
yield y
|
yield y
|
||||||
|
|
||||||
|
def second_pass(self):
|
||||||
|
'Locate paragraph boundaries in each column'
|
||||||
|
for region in self.regions:
|
||||||
|
region.collect_stats()
|
||||||
|
region.linearize()
|
||||||
|
|
||||||
|
|
||||||
class PDFDocument(object):
|
class PDFDocument(object):
|
||||||
|
|
||||||
@ -314,6 +381,7 @@ class PDFDocument(object):
|
|||||||
for page in self.pages:
|
for page in self.pages:
|
||||||
page.document_font_stats = self.font_size_stats
|
page.document_font_stats = self.font_size_stats
|
||||||
page.first_pass()
|
page.first_pass()
|
||||||
|
page.second_pass()
|
||||||
|
|
||||||
def collect_font_statistics(self):
|
def collect_font_statistics(self):
|
||||||
self.font_size_stats = {}
|
self.font_size_stats = {}
|
||||||
|
@ -14,10 +14,10 @@ from PyQt4.Qt import QWidget
|
|||||||
|
|
||||||
class PluginWidget(QWidget,Ui_Form):
|
class PluginWidget(QWidget,Ui_Form):
|
||||||
|
|
||||||
TITLE = _('EPUB/MOBI Options')
|
TITLE = _('E-book Options')
|
||||||
HELP = _('Options specific to')+' EPUB/MOBI '+_('output')
|
HELP = _('Options specific to')+' EPUB/MOBI '+_('output')
|
||||||
OPTION_FIELDS = [('exclude_genre','\[[\w ]*\]'),
|
OPTION_FIELDS = [('exclude_genre','\[[\w ]*\]'),
|
||||||
('exclude_tags','~'),
|
('exclude_tags','~,'+_('Catalog')),
|
||||||
('read_tag','+'),
|
('read_tag','+'),
|
||||||
('note_tag','*')]
|
('note_tag','*')]
|
||||||
|
|
||||||
|
@ -932,7 +932,7 @@ class DeviceGUI(object):
|
|||||||
if isinstance(job.exception, FreeSpaceError):
|
if isinstance(job.exception, FreeSpaceError):
|
||||||
where = 'in main memory.' if 'memory' in str(job.exception) \
|
where = 'in main memory.' if 'memory' in str(job.exception) \
|
||||||
else 'on the storage card.'
|
else 'on the storage card.'
|
||||||
titles = '\n'.join(['<li>'+mi['title']+'</li>' \
|
titles = '\n'.join(['<li>'+mi.title+'</li>' \
|
||||||
for mi in metadata])
|
for mi in metadata])
|
||||||
d = error_dialog(self, _('No space on device'),
|
d = error_dialog(self, _('No space on device'),
|
||||||
_('<p>Cannot upload books to device there '
|
_('<p>Cannot upload books to device there '
|
||||||
|
@ -46,18 +46,16 @@ class Catalog(QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
name = plugin.name.lower().replace(' ', '_')
|
name = plugin.name.lower().replace(' ', '_')
|
||||||
if type(plugin) in builtin_plugins:
|
if type(plugin) in builtin_plugins:
|
||||||
info("Adding widget for builtin Catalog plugin %s" % plugin.name)
|
|
||||||
try:
|
try:
|
||||||
catalog_widget = __import__('calibre.gui2.catalog.'+name,
|
catalog_widget = __import__('calibre.gui2.catalog.'+name,
|
||||||
fromlist=[1])
|
fromlist=[1])
|
||||||
pw = catalog_widget.PluginWidget()
|
pw = catalog_widget.PluginWidget()
|
||||||
info("Initializing %s" % name)
|
|
||||||
pw.initialize(name)
|
pw.initialize(name)
|
||||||
pw.ICON = I('forward.svg')
|
pw.ICON = I('forward.svg')
|
||||||
self.widgets.append(pw)
|
self.widgets.append(pw)
|
||||||
[self.fmts.append([file_type.upper(), pw.sync_enabled,pw]) for file_type in plugin.file_types]
|
[self.fmts.append([file_type.upper(), pw.sync_enabled,pw]) for file_type in plugin.file_types]
|
||||||
except ImportError:
|
except ImportError:
|
||||||
info("ImportError with %s" % name)
|
info("ImportError initializing %s" % name)
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
# Load dynamic tab
|
# Load dynamic tab
|
||||||
|
@ -522,7 +522,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
mi = MetaInformation(_('Calibre Quick Start Guide'), ['John Schember'])
|
mi = MetaInformation(_('Calibre Quick Start Guide'), ['John Schember'])
|
||||||
mi.author_sort = 'Schember, John'
|
mi.author_sort = 'Schember, John'
|
||||||
mi.comments = "A guide to get you up an running with calibre"
|
mi.comments = "A guide to get you up and running with calibre"
|
||||||
mi.publisher = 'calibre'
|
mi.publisher = 'calibre'
|
||||||
self.library_view.model().add_books([P('quick_start.epub')], ['epub'],
|
self.library_view.model().add_books([P('quick_start.epub')], ['epub'],
|
||||||
[mi])
|
[mi])
|
||||||
|
@ -178,7 +178,7 @@ class Document(QWebPage):
|
|||||||
|
|
||||||
def set_user_stylesheet(self):
|
def set_user_stylesheet(self):
|
||||||
raw = config().parse().user_css
|
raw = config().parse().user_css
|
||||||
raw = '::selection {background:#ffff00; color:#000;}\n'+raw
|
raw = '::selection {background:#ffff00; color:#000;}\nbody {background-color: white;}\n'+raw
|
||||||
data = 'data:text/css;charset=utf-8;base64,'
|
data = 'data:text/css;charset=utf-8;base64,'
|
||||||
data += b64encode(raw.encode('utf-8'))
|
data += b64encode(raw.encode('utf-8'))
|
||||||
self.settings().setUserStyleSheetUrl(QUrl(data))
|
self.settings().setUserStyleSheetUrl(QUrl(data))
|
||||||
|
@ -65,7 +65,10 @@ class CSV_XML(CatalogPlugin):
|
|||||||
for key in keys:
|
for key in keys:
|
||||||
log(" %s: %s" % (key, opts_dict[key]))
|
log(" %s: %s" % (key, opts_dict[key]))
|
||||||
|
|
||||||
# Get the sorted, filtered database as a dictionary
|
# If a list of ids are provided, don't use search_text
|
||||||
|
if opts.ids:
|
||||||
|
opts.search_text = None
|
||||||
|
|
||||||
data = self.search_sort_db(db, opts)
|
data = self.search_sort_db(db, opts)
|
||||||
|
|
||||||
if not len(data):
|
if not len(data):
|
||||||
@ -238,13 +241,22 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
help = _('Title of generated catalog used as title in metadata.\n'
|
help = _('Title of generated catalog used as title in metadata.\n'
|
||||||
"Default: '%default'\n"
|
"Default: '%default'\n"
|
||||||
"Applies to: ePub, MOBI output formats")),
|
"Applies to: ePub, MOBI output formats")),
|
||||||
|
Option('--debug-pipeline',
|
||||||
|
default=None,
|
||||||
|
dest='debug_pipeline',
|
||||||
|
help=_('Save the output from different stages of the conversion '
|
||||||
|
'pipeline to the specified '
|
||||||
|
'directory. Useful if you are unsure at which stage '
|
||||||
|
'of the conversion process a bug is occurring.\n'
|
||||||
|
'Default: None\n'
|
||||||
|
'Applies to: ePub, MOBI output formats')),
|
||||||
Option('--exclude-genre',
|
Option('--exclude-genre',
|
||||||
default='\[[\w ]*\]',
|
default='\[[\w ]*\]',
|
||||||
dest='exclude_genre',
|
dest='exclude_genre',
|
||||||
help=_("Regex describing tags to exclude as genres.\n" "Default: '%default' excludes bracketed tags, e.g. '[<tag>]'\n"
|
help=_("Regex describing tags to exclude as genres.\n" "Default: '%default' excludes bracketed tags, e.g. '[<tag>]'\n"
|
||||||
"Applies to: ePub, MOBI output formats")),
|
"Applies to: ePub, MOBI output formats")),
|
||||||
Option('--exclude-tags',
|
Option('--exclude-tags',
|
||||||
default='~',
|
default=('~,'+_('Catalog')),
|
||||||
dest='exclude_tags',
|
dest='exclude_tags',
|
||||||
help=_("Comma-separated list of tag words indicating book should be excluded from output. Case-insensitive.\n"
|
help=_("Comma-separated list of tag words indicating book should be excluded from output. Case-insensitive.\n"
|
||||||
"--exclude-tags=skip will match 'skip this book' and 'Skip will like this'.\n"
|
"--exclude-tags=skip will match 'skip this book' and 'Skip will like this'.\n"
|
||||||
@ -446,8 +458,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
# Number of discrete steps to catalog creation
|
# Number of discrete steps to catalog creation
|
||||||
current_step = 0
|
current_step = 0.0
|
||||||
total_steps = 13
|
total_steps = 13.0
|
||||||
|
|
||||||
# Used to xlate pubdate to friendly format
|
# Used to xlate pubdate to friendly format
|
||||||
MONTHS = ['January', 'February','March','April','May','June',
|
MONTHS = ['January', 'February','March','April','May','June',
|
||||||
@ -498,7 +510,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
self.__playOrder = 1
|
self.__playOrder = 1
|
||||||
self.__plugin = plugin
|
self.__plugin = plugin
|
||||||
self.__plugin_path = opts.plugin_path
|
self.__plugin_path = opts.plugin_path
|
||||||
self.__progressInt = 0
|
self.__progressInt = 0.0
|
||||||
self.__progressString = ''
|
self.__progressString = ''
|
||||||
self.__reporter = notification
|
self.__reporter = notification
|
||||||
self.__stylesheet = stylesheet
|
self.__stylesheet = stylesheet
|
||||||
@ -727,7 +739,6 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
shutil.copy(os.path.join(catalog_resources,file[1]),
|
shutil.copy(os.path.join(catalog_resources,file[1]),
|
||||||
os.path.join(self.catalogPath, file[0]))
|
os.path.join(self.catalogPath, file[0]))
|
||||||
|
|
||||||
|
|
||||||
def fetchBooksByTitle(self):
|
def fetchBooksByTitle(self):
|
||||||
|
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
@ -751,14 +762,14 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
search_terms.append("tag:%s" % tag)
|
search_terms.append("tag:%s" % tag)
|
||||||
search_phrase = "not (%s)" % " or ".join(search_terms)
|
search_phrase = "not (%s)" % " or ".join(search_terms)
|
||||||
|
|
||||||
# Allow for no search_text
|
# If a list of ids are provided, don't use search_text
|
||||||
if self.opts.search_text:
|
if self.opts.ids:
|
||||||
self.opts.search_text = self.opts.search_text + " " + search_phrase
|
|
||||||
else:
|
|
||||||
self.opts.search_text = search_phrase
|
self.opts.search_text = search_phrase
|
||||||
|
else:
|
||||||
if self.verbose and False:
|
if self.opts.search_text:
|
||||||
print "self.opts.search_text: %s" % self.opts.search_text
|
self.opts.search_text += " " + search_phrase
|
||||||
|
else:
|
||||||
|
self.opts.search_text = search_phrase
|
||||||
|
|
||||||
# Fetch the database as a dictionary
|
# Fetch the database as a dictionary
|
||||||
data = self.plugin.search_sort_db(self.db, self.opts)
|
data = self.plugin.search_sort_db(self.db, self.opts)
|
||||||
@ -807,7 +818,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
|
|
||||||
# Re-sort based on title_sort
|
# Re-sort based on title_sort
|
||||||
self.booksByTitle = sorted(titles,
|
self.booksByTitle = sorted(titles,
|
||||||
key=lambda x:(x['title_sort'], x['title_sort']))
|
key=lambda x:(x['title_sort'].upper(), x['title_sort'].upper()))
|
||||||
|
|
||||||
def fetchBooksByAuthor(self):
|
def fetchBooksByAuthor(self):
|
||||||
# Generate a list of titles sorted by author from the database
|
# Generate a list of titles sorted by author from the database
|
||||||
@ -815,23 +826,37 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
if self.verbose:
|
if self.verbose:
|
||||||
print self.updateProgressFullStep("fetchBooksByAuthor()")
|
print self.updateProgressFullStep("fetchBooksByAuthor()")
|
||||||
|
|
||||||
|
# Sort titles based on upper case authors
|
||||||
self.booksByAuthor = sorted(self.booksByTitle,
|
self.booksByAuthor = sorted(self.booksByTitle,
|
||||||
key=lambda x:(x['author_sort'], x['author_sort']))
|
key=lambda x:(x['author_sort'].upper(), x['author_sort'].upper()))
|
||||||
|
|
||||||
# Search_text already initialized
|
if True:
|
||||||
# Get the database sorted by author_sort
|
# Build the unique_authors set from existing data
|
||||||
self.opts.sort_by = 'author_sort'
|
authors = [(record['author'], record['author_sort']) for record in self.booksByAuthor]
|
||||||
data = self.plugin.search_sort_db(self.db, self.opts)
|
else:
|
||||||
|
# Search_text already initialized
|
||||||
|
# Get the database sorted by author_sort
|
||||||
|
self.opts.sort_by = 'author_sort'
|
||||||
|
data = self.plugin.search_sort_db(self.db, self.opts)
|
||||||
|
|
||||||
|
# GwR diagnostic: show sorted order
|
||||||
|
print "self.booksByAuthor in sort order:"
|
||||||
|
for book in self.booksByAuthor:
|
||||||
|
print "%s %s" % (book['author_sort'], book['title'])
|
||||||
|
print "data set in sort order:"
|
||||||
|
for book in data:
|
||||||
|
print "%s %s" % (book['author_sort'], book['title'])
|
||||||
|
|
||||||
|
# Build the unique_authors set
|
||||||
|
authors = []
|
||||||
|
for record in data:
|
||||||
|
# There may be multiple authors
|
||||||
|
author_list = []
|
||||||
|
for author in record['authors']:
|
||||||
|
author_list.append(author)
|
||||||
|
authors_concatenated = ", ".join(author_list)
|
||||||
|
authors.append((authors_concatenated, record['author_sort']))
|
||||||
|
|
||||||
# Build the unique_authors set
|
|
||||||
authors = []
|
|
||||||
for record in data:
|
|
||||||
# There may be multiple authors
|
|
||||||
author_list = []
|
|
||||||
for author in record['authors']:
|
|
||||||
author_list.append(author)
|
|
||||||
authors_concatenated = ", ".join(author_list)
|
|
||||||
authors.append((authors_concatenated, record['author_sort']))
|
|
||||||
|
|
||||||
# authors[] contains a list of all book authors, with multiple entries for multiple books by author
|
# authors[] contains a list of all book authors, with multiple entries for multiple books by author
|
||||||
# unique_authors : (([0]:friendly [1]:sort [2]:book_count))
|
# unique_authors : (([0]:friendly [1]:sort [2]:book_count))
|
||||||
@ -860,7 +885,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
unique_authors.append((current_author[0], current_author[1],
|
unique_authors.append((current_author[0], current_author[1],
|
||||||
books_by_current_author))
|
books_by_current_author))
|
||||||
|
|
||||||
if self.verbose and False:
|
if False and self.verbose:
|
||||||
print "\nget_books_by_author(): %d unique authors" % len(unique_authors)
|
print "\nget_books_by_author(): %d unique authors" % len(unique_authors)
|
||||||
for author in unique_authors[0:3]:
|
for author in unique_authors[0:3]:
|
||||||
print "%s" % author[0]
|
print "%s" % author[0]
|
||||||
@ -880,7 +905,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
print "%3s: %s - %s" % (title['id'], title['title'], title['author'])
|
print "%3s: %s - %s" % (title['id'], title['title'], title['author'])
|
||||||
|
|
||||||
self.updateProgressMicroStep("generating book descriptions ...",
|
self.updateProgressMicroStep("generating book descriptions ...",
|
||||||
100*title_num/len(self.booksByTitle))
|
float(title_num*100/len(self.booksByTitle))/100)
|
||||||
|
|
||||||
# Generate the header
|
# Generate the header
|
||||||
soup = self.generateHTMLDescriptionHeader("%s" % title['title'])
|
soup = self.generateHTMLDescriptionHeader("%s" % title['title'])
|
||||||
@ -917,7 +942,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
authorTag = body.find(attrs={'class':'author'})
|
authorTag = body.find(attrs={'class':'author'})
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor", self.generateAuthorAnchor(title['author']))
|
aTag['href'] = "%s.html#%s" % ("ByAlphaAuthor", self.generateAuthorAnchor(title['author']))
|
||||||
aTag.insert(0, escape(title['author']))
|
#aTag.insert(0, escape(title['author']))
|
||||||
|
aTag.insert(0, title['author'])
|
||||||
authorTag.insert(0, NavigableString("by "))
|
authorTag.insert(0, NavigableString("by "))
|
||||||
authorTag.insert(1, aTag)
|
authorTag.insert(1, aTag)
|
||||||
|
|
||||||
@ -938,6 +964,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
# Insert a spacer to match the author indent
|
# Insert a spacer to match the author indent
|
||||||
fontTag = Tag(soup,"font")
|
fontTag = Tag(soup,"font")
|
||||||
fontTag['style'] = 'color:white;font-size:large'
|
fontTag['style'] = 'color:white;font-size:large'
|
||||||
|
if self.opts.fmt == 'epub':
|
||||||
|
fontTag['style'] += ';opacity: 0.0'
|
||||||
fontTag.insert(0, NavigableString("by "))
|
fontTag.insert(0, NavigableString("by "))
|
||||||
tagsTag.insert(ttc, fontTag)
|
tagsTag.insert(ttc, fontTag)
|
||||||
ttc += 1
|
ttc += 1
|
||||||
@ -948,6 +976,8 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
aTag.insert(0,escape(NavigableString(tag)))
|
aTag.insert(0,escape(NavigableString(tag)))
|
||||||
emTag = Tag(soup, "em")
|
emTag = Tag(soup, "em")
|
||||||
emTag.insert(0, aTag)
|
emTag.insert(0, aTag)
|
||||||
|
if ttc < len(title['tags']):
|
||||||
|
emTag.insert(1, NavigableString(', '))
|
||||||
tagsTag.insert(ttc, emTag)
|
tagsTag.insert(ttc, emTag)
|
||||||
ttc += 1
|
ttc += 1
|
||||||
|
|
||||||
@ -1054,15 +1084,15 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
|
|
||||||
# Loop through the books by title
|
# Loop through the books by title
|
||||||
for book in self.booksByTitle:
|
for book in self.booksByTitle:
|
||||||
if book['title_sort'][0] != current_letter :
|
if book['title_sort'][0].upper() != current_letter :
|
||||||
# Start a new letter
|
# Start a new letter
|
||||||
current_letter = book['title_sort'][0]
|
current_letter = book['title_sort'][0].upper()
|
||||||
pIndexTag = Tag(soup, "p")
|
pIndexTag = Tag(soup, "p")
|
||||||
pIndexTag['class'] = "letter_index"
|
pIndexTag['class'] = "letter_index"
|
||||||
aTag = Tag(soup, "a")
|
aTag = Tag(soup, "a")
|
||||||
aTag['name'] = "%stitles" % book['title_sort'][0]
|
aTag['name'] = "%stitles" % book['title_sort'][0].upper()
|
||||||
pIndexTag.insert(0,aTag)
|
pIndexTag.insert(0,aTag)
|
||||||
pIndexTag.insert(1,NavigableString(book['title_sort'][0]))
|
pIndexTag.insert(1,NavigableString(book['title_sort'][0].upper()))
|
||||||
divTag.insert(dtc,pIndexTag)
|
divTag.insert(dtc,pIndexTag)
|
||||||
dtc += 1
|
dtc += 1
|
||||||
|
|
||||||
@ -1169,7 +1199,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
book_count = 0
|
book_count = 0
|
||||||
for book in self.booksByAuthor:
|
for book in self.booksByAuthor:
|
||||||
book_count += 1
|
book_count += 1
|
||||||
if book['author_sort'][0] != current_letter :
|
if book['author_sort'][0].upper() != current_letter :
|
||||||
'''
|
'''
|
||||||
# Start a new letter - anchor only, hidden
|
# Start a new letter - anchor only, hidden
|
||||||
current_letter = book['author_sort'][0].upper()
|
current_letter = book['author_sort'][0].upper()
|
||||||
@ -1709,6 +1739,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
books_by_letter = []
|
books_by_letter = []
|
||||||
if single_article_per_section:
|
if single_article_per_section:
|
||||||
# Create a single article for all books in this section
|
# Create a single article for all books in this section
|
||||||
|
# THIS CODE NEEDS TO BE REVIEWED FOR .upper()
|
||||||
single_list = []
|
single_list = []
|
||||||
for book in self.booksByTitle:
|
for book in self.booksByTitle:
|
||||||
single_list.append(book)
|
single_list.append(book)
|
||||||
@ -1721,19 +1752,19 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
# Loop over the titles, find start of each letter, add description_preview_count books
|
# Loop over the titles, find start of each letter, add description_preview_count books
|
||||||
current_letter = self.booksByTitle[0]['title_sort'][0]
|
current_letter = self.booksByTitle[0]['title_sort'][0].upper()
|
||||||
title_letters = [current_letter]
|
title_letters = [current_letter]
|
||||||
current_book_list = []
|
current_book_list = []
|
||||||
current_book = ""
|
current_book = ""
|
||||||
for book in self.booksByTitle:
|
for book in self.booksByTitle:
|
||||||
if book['title_sort'][0] != current_letter:
|
if book['title_sort'][0].upper() != current_letter:
|
||||||
# Save the old list
|
# Save the old list
|
||||||
book_list = " • ".join(current_book_list)
|
book_list = " • ".join(current_book_list)
|
||||||
short_description = self.generateShortDescription(self.formatNCXText(book_list))
|
short_description = self.generateShortDescription(self.formatNCXText(book_list))
|
||||||
books_by_letter.append(short_description)
|
books_by_letter.append(short_description)
|
||||||
|
|
||||||
# Start the new list
|
# Start the new list
|
||||||
current_letter = book['title_sort'][0]
|
current_letter = book['title_sort'][0].upper()
|
||||||
title_letters.append(current_letter)
|
title_letters.append(current_letter)
|
||||||
current_book = book['title']
|
current_book = book['title']
|
||||||
current_book_list = [book['title']]
|
current_book_list = [book['title']]
|
||||||
@ -1810,20 +1841,19 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
self.playOrder += 1
|
self.playOrder += 1
|
||||||
navLabelTag = Tag(soup, 'navLabel')
|
navLabelTag = Tag(soup, 'navLabel')
|
||||||
textTag = Tag(soup, 'text')
|
textTag = Tag(soup, 'text')
|
||||||
# textTag.insert(0, NavigableString('%s (%d)' % (section_title,len(sorted_authors))))
|
|
||||||
textTag.insert(0, NavigableString('%s' % tocTitle))
|
textTag.insert(0, NavigableString('%s' % tocTitle))
|
||||||
navLabelTag.insert(0, textTag)
|
navLabelTag.insert(0, textTag)
|
||||||
nptc = 0
|
nptc = 0
|
||||||
navPointTag.insert(nptc, navLabelTag)
|
navPointTag.insert(nptc, navLabelTag)
|
||||||
nptc += 1
|
nptc += 1
|
||||||
contentTag = Tag(soup,"content")
|
contentTag = Tag(soup,"content")
|
||||||
# contentTag['src'] = "%s#%s" % (HTML_file, file_ID)
|
|
||||||
contentTag['src'] = "%s#section_start" % HTML_file
|
contentTag['src'] = "%s#section_start" % HTML_file
|
||||||
navPointTag.insert(nptc, contentTag)
|
navPointTag.insert(nptc, contentTag)
|
||||||
nptc += 1
|
nptc += 1
|
||||||
|
|
||||||
if single_article_per_section:
|
if single_article_per_section:
|
||||||
# Create a single article for all authors in this section
|
# Create a single article for all authors in this section
|
||||||
|
# THIS CODE NEEDS TO BE REVIEWED FOR .upper()
|
||||||
|
|
||||||
# Build a formatted author range for article preview
|
# Build a formatted author range for article preview
|
||||||
single_list = []
|
single_list = []
|
||||||
@ -1841,7 +1871,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
# Loop over the sorted_authors list, find start of each letter, add description_preview_count artists
|
# Loop over the sorted_authors list, find start of each letter, add description_preview_count artists
|
||||||
# sorted_authors[0]:friendly [1]:author_sort [2]:book_count
|
# sorted_authors[0]:friendly [1]:author_sort [2]:book_count
|
||||||
master_author_list = []
|
master_author_list = []
|
||||||
current_letter = self.authors[0][1][0]
|
current_letter = self.authors[0][1][0].upper()
|
||||||
current_author_list = []
|
current_author_list = []
|
||||||
for author in self.authors:
|
for author in self.authors:
|
||||||
if author[1][0] != current_letter:
|
if author[1][0] != current_letter:
|
||||||
@ -1854,7 +1884,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
master_author_list.append((author_list, current_letter))
|
master_author_list.append((author_list, current_letter))
|
||||||
|
|
||||||
# Start the new list
|
# Start the new list
|
||||||
current_letter = author[1][0]
|
current_letter = author[1][0].upper()
|
||||||
current_author_list = [author[0]]
|
current_author_list = [author[0]]
|
||||||
else:
|
else:
|
||||||
if len(current_author_list) < self.descriptionClip:
|
if len(current_author_list) < self.descriptionClip:
|
||||||
@ -1872,7 +1902,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
for authors in master_author_list:
|
for authors in master_author_list:
|
||||||
navPointByLetterTag = Tag(soup, 'navPoint')
|
navPointByLetterTag = Tag(soup, 'navPoint')
|
||||||
navPointByLetterTag['class'] = "article"
|
navPointByLetterTag['class'] = "article"
|
||||||
navPointByLetterTag['id'] = "%sauthors-ID" % (authors[1])
|
navPointByLetterTag['id'] = "%sauthors-ID" % (authors[1].upper())
|
||||||
navPointTag['playOrder'] = self.playOrder
|
navPointTag['playOrder'] = self.playOrder
|
||||||
self.playOrder += 1
|
self.playOrder += 1
|
||||||
navLabelTag = Tag(soup, 'navLabel')
|
navLabelTag = Tag(soup, 'navLabel')
|
||||||
@ -1880,7 +1910,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
if single_article_per_section:
|
if single_article_per_section:
|
||||||
textTag.insert(0, NavigableString("All books sorted by author"))
|
textTag.insert(0, NavigableString("All books sorted by author"))
|
||||||
else:
|
else:
|
||||||
textTag.insert(0, NavigableString("Authors beginning with '%s'" % (authors[1])))
|
textTag.insert(0, NavigableString("Authors beginning with '%s'" % (authors[1].upper())))
|
||||||
navLabelTag.insert(0, textTag)
|
navLabelTag.insert(0, textTag)
|
||||||
navPointByLetterTag.insert(0,navLabelTag)
|
navPointByLetterTag.insert(0,navLabelTag)
|
||||||
contentTag = Tag(soup, 'content')
|
contentTag = Tag(soup, 'content')
|
||||||
@ -1888,7 +1918,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
if single_article_per_section:
|
if single_article_per_section:
|
||||||
contentTag['src'] = "%s#byauthor" % HTML_file
|
contentTag['src'] = "%s#byauthor" % HTML_file
|
||||||
else:
|
else:
|
||||||
contentTag['src'] = "%s#%sauthors" % (HTML_file, authors[1])
|
contentTag['src'] = "%s#%sauthors" % (HTML_file, authors[1].upper())
|
||||||
|
|
||||||
navPointByLetterTag.insert(1,contentTag)
|
navPointByLetterTag.insert(1,contentTag)
|
||||||
cmTag = Tag(soup, '%s' % 'mbp:meta' if self.generateForMobigen else 'calibre:meta')
|
cmTag = Tag(soup, '%s' % 'mbp:meta' if self.generateForMobigen else 'calibre:meta')
|
||||||
@ -2476,6 +2506,7 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
pw.MagickThumbnailImage(thumb, 75, 100)
|
pw.MagickThumbnailImage(thumb, 75, 100)
|
||||||
pw.MagickWriteImage(thumb, os.path.join(image_dir, thumb_file))
|
pw.MagickWriteImage(thumb, os.path.join(image_dir, thumb_file))
|
||||||
pw.DestroyMagickWand(thumb)
|
pw.DestroyMagickWand(thumb)
|
||||||
|
pw.DestroyMagickWand(img)
|
||||||
except IOError:
|
except IOError:
|
||||||
print "generate_thumbnail() IOError with %s" % title['title']
|
print "generate_thumbnail() IOError with %s" % title['title']
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
@ -2506,23 +2537,25 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
|
|
||||||
self.current_step += 1
|
self.current_step += 1
|
||||||
self.progressString = description
|
self.progressString = description
|
||||||
self.progressInt = ((self.current_step-1)*100)/self.total_steps
|
self.progressInt = float((self.current_step-1)/self.total_steps)
|
||||||
self.reporter(self.progressInt, self.progressString)
|
self.reporter(self.progressInt/100., self.progressString)
|
||||||
return "%d%% %s" % (self.progressInt, self.progressString)
|
return "%.2f%% %s" % (self.progressInt, self.progressString)
|
||||||
|
|
||||||
def updateProgressMicroStep(self, description, micro_step_pct):
|
def updateProgressMicroStep(self, description, micro_step_pct):
|
||||||
step_range = 100/self.total_steps
|
step_range = 100/self.total_steps
|
||||||
self.progressString = description
|
self.progressString = description
|
||||||
self.progressInt = ((self.current_step-1)*100)/self.total_steps + (micro_step_pct*step_range)/100
|
coarse_progress = float((self.current_step-1)/self.total_steps)
|
||||||
self.reporter(self.progressInt, self.progressString)
|
fine_progress = float((micro_step_pct*step_range)/100)
|
||||||
return "%d%% %s" % (self.progressInt, self.progressString)
|
self.progressInt = coarse_progress + fine_progress
|
||||||
|
self.reporter(self.progressInt/100., self.progressString)
|
||||||
|
return "%.2f%% %s" % (self.progressInt, self.progressString)
|
||||||
|
|
||||||
def run(self, path_to_output, opts, db, notification=DummyReporter()):
|
def run(self, path_to_output, opts, db, notification=DummyReporter()):
|
||||||
from calibre.utils.logging import Log
|
from calibre.utils.logging import Log
|
||||||
self.opts = opts
|
|
||||||
|
|
||||||
log = Log()
|
log = Log()
|
||||||
opts.fmt = self.fmt = path_to_output.rpartition('.')[2]
|
opts.fmt = self.fmt = path_to_output.rpartition('.')[2]
|
||||||
|
self.opts = opts
|
||||||
|
|
||||||
# Add local options
|
# Add local options
|
||||||
opts.creator = "calibre"
|
opts.creator = "calibre"
|
||||||
@ -2532,16 +2565,22 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
opts.plugin_path = self.plugin_path
|
opts.plugin_path = self.plugin_path
|
||||||
|
|
||||||
if opts.verbose:
|
if opts.verbose:
|
||||||
|
opts_dict = vars(opts)
|
||||||
log("%s:run" % self.name)
|
log("%s:run" % self.name)
|
||||||
log(" path_to_output: %s" % path_to_output)
|
log(" path_to_output: %s" % path_to_output)
|
||||||
log(" Output format: %s" % self.fmt)
|
log(" Output format: %s" % self.fmt)
|
||||||
|
if opts_dict['ids']:
|
||||||
|
log(" Book count: %d" % len(opts_dict['ids']))
|
||||||
# Display opts
|
# Display opts
|
||||||
opts_dict = vars(opts)
|
|
||||||
keys = opts_dict.keys()
|
keys = opts_dict.keys()
|
||||||
keys.sort()
|
keys.sort()
|
||||||
log(" opts:")
|
log(" opts:")
|
||||||
for key in keys:
|
for key in keys:
|
||||||
|
if key == 'ids':
|
||||||
|
if opts_dict[key]:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
log(" %s: (all)" % key)
|
||||||
log(" %s: %s" % (key, opts_dict[key]))
|
log(" %s: %s" % (key, opts_dict[key]))
|
||||||
|
|
||||||
# Launch the Catalog builder
|
# Launch the Catalog builder
|
||||||
@ -2552,6 +2591,11 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
|
|
||||||
recommendations = []
|
recommendations = []
|
||||||
|
|
||||||
|
dp = getattr(opts, 'debug_pipeline', None)
|
||||||
|
if dp is not None:
|
||||||
|
recommendations.append(('debug_pipeline', dp,
|
||||||
|
OptionRecommendation.HIGH))
|
||||||
|
|
||||||
if opts.fmt == 'mobi' and opts.output_profile and opts.output_profile.startswith("kindle"):
|
if opts.fmt == 'mobi' and opts.output_profile and opts.output_profile.startswith("kindle"):
|
||||||
recommendations.append(('output_profile', opts.output_profile,
|
recommendations.append(('output_profile', opts.output_profile,
|
||||||
OptionRecommendation.HIGH))
|
OptionRecommendation.HIGH))
|
||||||
@ -2566,4 +2610,3 @@ class EPUB_MOBI(CatalogPlugin):
|
|||||||
plumber.merge_ui_recommendations(recommendations)
|
plumber.merge_ui_recommendations(recommendations)
|
||||||
|
|
||||||
plumber.run()
|
plumber.run()
|
||||||
|
|
||||||
|
@ -112,6 +112,7 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250,
|
|||||||
format_args['title'] = mi.title
|
format_args['title'] = mi.title
|
||||||
if mi.authors:
|
if mi.authors:
|
||||||
format_args['authors'] = mi.format_authors()
|
format_args['authors'] = mi.format_authors()
|
||||||
|
format_args['author'] = format_args['authors']
|
||||||
if mi.author_sort:
|
if mi.author_sort:
|
||||||
format_args['author_sort'] = mi.author_sort
|
format_args['author_sort'] = mi.author_sort
|
||||||
if mi.tags:
|
if mi.tags:
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: calibre 0.6.34\n"
|
"Project-Id-Version: calibre 0.6.35\n"
|
||||||
"POT-Creation-Date: 2010-01-21 20:05+MST\n"
|
"POT-Creation-Date: 2010-01-22 16:20+MST\n"
|
||||||
"PO-Revision-Date: 2010-01-21 20:05+MST\n"
|
"PO-Revision-Date: 2010-01-22 16:20+MST\n"
|
||||||
"Last-Translator: Automatically generated\n"
|
"Last-Translator: Automatically generated\n"
|
||||||
"Language-Team: LANGUAGE\n"
|
"Language-Team: LANGUAGE\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -216,19 +216,19 @@ msgstr ""
|
|||||||
msgid "Set metadata from %s files"
|
msgid "Set metadata from %s files"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:99
|
#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:102
|
||||||
msgid "Conversion Input"
|
msgid "Conversion Input"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:122
|
#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:125
|
||||||
msgid "Specify the character encoding of the input document. If set this option will override any encoding declared by the document itself. Particularly useful for documents that do not declare an encoding or that have erroneous encoding declarations."
|
msgid "Specify the character encoding of the input document. If set this option will override any encoding declared by the document itself. Particularly useful for documents that do not declare an encoding or that have erroneous encoding declarations."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:225
|
#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:228
|
||||||
msgid "Conversion Output"
|
msgid "Conversion Output"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:239
|
#: /home/kovid/work/calibre/src/calibre/customize/conversion.py:242
|
||||||
msgid "If specified, the output plugin will try to create output that is as human readable as possible. May not have any effect for some output plugins."
|
msgid "If specified, the output plugin will try to create output that is as human readable as possible. May not have any effect for some output plugins."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2134,6 +2134,7 @@ msgid "CSV/XML Options"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml.py:17
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml.py:17
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi.py:18
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input.py:16
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input.py:16
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output.py:16
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output.py:16
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input.py:13
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input.py:13
|
||||||
@ -2151,6 +2152,7 @@ msgid "Options specific to"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml.py:17
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml.py:17
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi.py:18
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output.py:16
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output.py:16
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output.py:15
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output.py:15
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:20
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:20
|
||||||
@ -2162,7 +2164,8 @@ msgstr ""
|
|||||||
msgid "output"
|
msgid "output"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml_ui.py:34
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml_ui.py:36
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:51
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_tab_template_ui.py:27
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_tab_template_ui.py:27
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:84
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:84
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:49
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:49
|
||||||
@ -2193,10 +2196,34 @@ msgstr ""
|
|||||||
msgid "Form"
|
msgid "Form"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml_ui.py:35
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_csv_xml_ui.py:37
|
||||||
msgid "Fields to include in output:"
|
msgid "Fields to include in output:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi.py:17
|
||||||
|
msgid "E-book Options"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#:
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:52
|
||||||
|
msgid "Tags to exclude as genres (regex):"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#:
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:53
|
||||||
|
msgid "'Don't include this book' tag:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#:
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:54
|
||||||
|
msgid "'Mark this book as read' tag:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#:
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_epub_mobi_ui.py:55
|
||||||
|
msgid "Additional note tag prefix:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#:
|
#:
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_tab_template_ui.py:28
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_tab_template_ui.py:28
|
||||||
msgid "Tab template for catalog.ui"
|
msgid "Tab template for catalog.ui"
|
||||||
@ -2799,7 +2826,7 @@ msgid "RB Output"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder.py:77
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder.py:77
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1633
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1637
|
||||||
msgid "Choose the format to view"
|
msgid "Choose the format to view"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3331,7 +3358,7 @@ msgstr ""
|
|||||||
msgid "&Next"
|
msgid "&Next"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog.py:38
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/catalog.py:37
|
||||||
msgid "My Books"
|
msgid "My Books"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3457,7 +3484,7 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:477
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:477
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:821
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:821
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:158
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:158
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1242
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1246
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:53
|
#: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:53
|
||||||
msgid "Error"
|
msgid "Error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -5398,7 +5425,7 @@ msgid "Save to disk in a single directory"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:306
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:306
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1741
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1745
|
||||||
msgid "Save only %s format to disk"
|
msgid "Save only %s format to disk"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -5453,7 +5480,7 @@ msgid "Calibre Library"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:485
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:485
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1897
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1901
|
||||||
msgid "Choose a location for your ebook library."
|
msgid "Choose a location for your ebook library."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -5558,8 +5585,8 @@ msgid "Cannot delete"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1075
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1075
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1627
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1631
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1646
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1650
|
||||||
msgid "No book selected"
|
msgid "No book selected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -5567,219 +5594,227 @@ msgstr ""
|
|||||||
msgid "Choose formats to be deleted"
|
msgid "Choose formats to be deleted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1101
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1103
|
||||||
msgid "Choose formats <b>not</b> to be deleted"
|
msgid "Choose formats <b>not</b> to be deleted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1137
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1141
|
||||||
msgid "The selected books will be <b>permanently deleted</b> and the files removed from your computer. Are you sure?"
|
msgid "The selected books will be <b>permanently deleted</b> and the files removed from your computer. Are you sure?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1164
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1168
|
||||||
msgid "Deleting books from device."
|
msgid "Deleting books from device."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1195
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1199
|
||||||
msgid "Cannot download metadata"
|
msgid "Cannot download metadata"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1196
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1200
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1253
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1257
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1286
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1290
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1311
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1315
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1370
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1374
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1483
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1487
|
||||||
msgid "No books selected"
|
msgid "No books selected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1211
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1215
|
||||||
msgid "social metadata"
|
msgid "social metadata"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1213
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1217
|
||||||
msgid "covers"
|
msgid "covers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1213
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1217
|
||||||
msgid "metadata"
|
msgid "metadata"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1215
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1219
|
||||||
msgid "Downloading %s for %d book(s)"
|
msgid "Downloading %s for %d book(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1237
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1241
|
||||||
msgid "Failed to download some metadata"
|
msgid "Failed to download some metadata"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1238
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1242
|
||||||
msgid "Failed to download metadata for the following:"
|
msgid "Failed to download metadata for the following:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1241
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1245
|
||||||
msgid "Failed to download metadata:"
|
msgid "Failed to download metadata:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1252
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1256
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1285
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1289
|
||||||
msgid "Cannot edit metadata"
|
msgid "Cannot edit metadata"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1310
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1314
|
||||||
msgid "Cannot save to disk"
|
msgid "Cannot save to disk"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1313
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1317
|
||||||
msgid "Choose destination directory"
|
msgid "Choose destination directory"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1340
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1344
|
||||||
msgid "Error while saving"
|
msgid "Error while saving"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1341
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1345
|
||||||
msgid "There was an error while saving."
|
msgid "There was an error while saving."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1348
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1352
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1349
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1353
|
||||||
msgid "Could not save some books"
|
msgid "Could not save some books"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1350
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1354
|
||||||
msgid "Click the show details button to see which ones."
|
msgid "Click the show details button to see which ones."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1371
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1375
|
||||||
msgid "No books selected to generate catalog for"
|
msgid "No books selected to generate catalog for"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1388
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1392
|
||||||
msgid "Generating %s catalog..."
|
msgid "Generating %s catalog..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1399
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1403
|
||||||
msgid "Catalog generated."
|
msgid "Catalog generated."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1417
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1406
|
||||||
|
msgid "Export Catalog Directory"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1407
|
||||||
|
msgid "Select destination for %s.%s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1421
|
||||||
msgid "Fetching news from "
|
msgid "Fetching news from "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1431
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1435
|
||||||
msgid " fetched."
|
msgid " fetched."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1482
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1486
|
||||||
msgid "Cannot convert"
|
msgid "Cannot convert"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1511
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1515
|
||||||
msgid "Starting conversion of %d book(s)"
|
msgid "Starting conversion of %d book(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1627
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1631
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1683
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1687
|
||||||
msgid "Cannot view"
|
msgid "Cannot view"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1645
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1649
|
||||||
msgid "Cannot open folder"
|
msgid "Cannot open folder"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1667
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1671
|
||||||
msgid "Multiple Books Selected"
|
msgid "Multiple Books Selected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1668
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1672
|
||||||
msgid "You are attempting to open %d books. Opening too many books at once can be slow and have a negative effect on the responsiveness of your computer. Once started the process cannot be stopped until complete. Do you wish to continue?"
|
msgid "You are attempting to open %d books. Opening too many books at once can be slow and have a negative effect on the responsiveness of your computer. Once started the process cannot be stopped until complete. Do you wish to continue?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1684
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1688
|
||||||
msgid "%s has no available formats."
|
msgid "%s has no available formats."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1725
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1729
|
||||||
msgid "Cannot configure"
|
msgid "Cannot configure"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1726
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1730
|
||||||
msgid "Cannot configure while there are running jobs."
|
msgid "Cannot configure while there are running jobs."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1769
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1773
|
||||||
msgid "No detailed info available"
|
msgid "No detailed info available"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1770
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1774
|
||||||
msgid "No detailed information is available for books on the device."
|
msgid "No detailed information is available for books on the device."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1825
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1829
|
||||||
msgid "Error talking to device"
|
msgid "Error talking to device"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1826
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1830
|
||||||
msgid "There was a temporary error talking to the device. Please unplug and reconnect the device and or reboot."
|
msgid "There was a temporary error talking to the device. Please unplug and reconnect the device and or reboot."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1849
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1853
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1877
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1881
|
||||||
msgid "Conversion Error"
|
msgid "Conversion Error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1850
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1854
|
||||||
msgid "<p>Could not convert: %s<p>It is a <a href=\"%s\">DRM</a>ed book. You must first remove the DRM using third party tools."
|
msgid "<p>Could not convert: %s<p>It is a <a href=\"%s\">DRM</a>ed book. You must first remove the DRM using third party tools."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1863
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1867
|
||||||
msgid "Recipe Disabled"
|
msgid "Recipe Disabled"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1878
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1882
|
||||||
msgid "<b>Failed</b>"
|
msgid "<b>Failed</b>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1906
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1910
|
||||||
msgid "Invalid library location"
|
msgid "Invalid library location"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1907
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1911
|
||||||
msgid "Could not access %s. Using %s as the library."
|
msgid "Could not access %s. Using %s as the library."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1957
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1961
|
||||||
msgid "is the result of the efforts of many volunteers from all over the world. If you find it useful, please consider donating to support its development."
|
msgid "is the result of the efforts of many volunteers from all over the world. If you find it useful, please consider donating to support its development."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1982
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1986
|
||||||
msgid "There are active jobs. Are you sure you want to quit?"
|
msgid "There are active jobs. Are you sure you want to quit?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1985
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1989
|
||||||
msgid ""
|
msgid ""
|
||||||
" is communicating with the device!<br>\n"
|
" is communicating with the device!<br>\n"
|
||||||
" Quitting may cause corruption on the device.<br>\n"
|
" Quitting may cause corruption on the device.<br>\n"
|
||||||
" Are you sure you want to quit?"
|
" Are you sure you want to quit?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1989
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1993
|
||||||
msgid "WARNING: Active jobs"
|
msgid "WARNING: Active jobs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2041
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2045
|
||||||
msgid "will keep running in the system tray. To close it, choose <b>Quit</b> in the context menu of the system tray."
|
msgid "will keep running in the system tray. To close it, choose <b>Quit</b> in the context menu of the system tray."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2060
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2064
|
||||||
msgid "<span style=\"color:red; font-weight:bold\">Latest version: <a href=\"%s\">%s</a></span>"
|
msgid "<span style=\"color:red; font-weight:bold\">Latest version: <a href=\"%s\">%s</a></span>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2068
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2072
|
||||||
msgid "Update available"
|
msgid "Update available"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2069
|
#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:2073
|
||||||
msgid "%s has been updated to version %s. See the <a href=\"http://calibre-ebook.com/whats-new\">new features</a>. Visit the download page?"
|
msgid "%s has been updated to version %s. See the <a href=\"http://calibre-ebook.com/whats-new\">new features</a>. Visit the download page?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -5991,7 +6026,7 @@ msgstr ""
|
|||||||
msgid "The standard font type"
|
msgid "The standard font type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/documentview.py:407
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/documentview.py:408
|
||||||
msgid "&Lookup in dictionary"
|
msgid "&Lookup in dictionary"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -6524,7 +6559,7 @@ msgstr ""
|
|||||||
msgid "The maximum number of matches to return per OPDS query. This affects Stanza, WordPlayer, etc. integration."
|
msgid "The maximum number of matches to return per OPDS query. This affects Stanza, WordPlayer, etc. integration."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/catalog.py:28
|
#: /home/kovid/work/calibre/src/calibre/library/catalog.py:34
|
||||||
msgid ""
|
msgid ""
|
||||||
"The fields to output when cataloging books in the database. Should be a comma-separated list of fields.\n"
|
"The fields to output when cataloging books in the database. Should be a comma-separated list of fields.\n"
|
||||||
"Available fields: %s.\n"
|
"Available fields: %s.\n"
|
||||||
@ -6532,7 +6567,7 @@ msgid ""
|
|||||||
"Applies to: CSV, XML output formats"
|
"Applies to: CSV, XML output formats"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/catalog.py:37
|
#: /home/kovid/work/calibre/src/calibre/library/catalog.py:43
|
||||||
msgid ""
|
msgid ""
|
||||||
"Output field to sort on.\n"
|
"Output field to sort on.\n"
|
||||||
"Available fields: author_sort, id, rating, size, timestamp, title.\n"
|
"Available fields: author_sort, id, rating, size, timestamp, title.\n"
|
||||||
@ -6540,6 +6575,49 @@ msgid ""
|
|||||||
"Applies to: CSV, XML output formats"
|
"Applies to: CSV, XML output formats"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/library/catalog.py:238
|
||||||
|
msgid ""
|
||||||
|
"Title of generated catalog used as title in metadata.\n"
|
||||||
|
"Default: '%default'\n"
|
||||||
|
"Applies to: ePub, MOBI output formats"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/library/catalog.py:244
|
||||||
|
msgid ""
|
||||||
|
"Regex describing tags to exclude as genres.\n"
|
||||||
|
"Default: '%default' excludes bracketed tags, e.g. '[<tag>]'\n"
|
||||||
|
"Applies to: ePub, MOBI output formats"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/library/catalog.py:249
|
||||||
|
msgid ""
|
||||||
|
"Comma-separated list of tag words indicating book should be excluded from output. Case-insensitive.\n"
|
||||||
|
"--exclude-tags=skip will match 'skip this book' and 'Skip will like this'.\n"
|
||||||
|
"Default: '%default'\n"
|
||||||
|
"Applies to: ePub, MOBI output formats"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/library/catalog.py:256
|
||||||
|
msgid ""
|
||||||
|
"Tag indicating book has been read.\n"
|
||||||
|
"Default: '%default'\n"
|
||||||
|
"Applies to: ePub, MOBI output formats"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/library/catalog.py:261
|
||||||
|
msgid ""
|
||||||
|
"Tag prefix for user notes, e.g. '*Jeff might enjoy reading this'.\n"
|
||||||
|
"Default: '%default'\n"
|
||||||
|
"Applies to: ePub, MOBI output formats"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/library/catalog.py:267
|
||||||
|
msgid ""
|
||||||
|
"Specifies the output profile. In some cases, an output profile is required to optimize the catalog for the device. For example, 'kindle' or 'kindle_dx' creates a structured Table of Contents with Sections and Articles.\n"
|
||||||
|
"Default: '%default'\n"
|
||||||
|
"Applies to: ePub, MOBI output formats"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:121
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:121
|
||||||
msgid "Path to the calibre library. Default is to use the path stored in the settings."
|
msgid "Path to the calibre library. Default is to use the path stored in the settings."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user