This commit is contained in:
GRiker 2012-09-28 06:55:51 -06:00
commit a6f73264d6
113 changed files with 47251 additions and 40551 deletions

View File

@ -19,6 +19,51 @@
# new recipes: # new recipes:
# - title: # - title:
- version: 0.9.0
date: 2012-09-28
new features:
- title: "For a summary of the major changes in calibre between 0.8 and 0.9, see http://calibre-ebook.com/new-in/nine"
type: major
bug fixes:
- title: "KF8 Output: Fix handling of & < and > entities in the text. They were sometimes being incorrectly unescaped."
- title: "Calibre portable: Add a manifest to the portable installer exe to prevent the application compatibility wizard from warning about a possible failed installation on windows 7. Also fixes installer requiring admin privileges on some computers"
tickets: [1057042]
- title: "EPUB metadata: Fix book producer not being set when updating EPUB metadata"
- title: "EPUB metadata: Fix incorrect namespace on the role attribute of <dc:creator> tags when updating the metadata in EPUB"
- title: "Get Books: Fix incorrect price retrieval from ebooks.com."
tickets: [1055785]
- title: "MTP windows driver: Fix main memory and storage card sometimes swapped"
tickets: [1055129]
- title: "PDF Output: On windows, remove any embedded fonts before generating the PDF as on windows, Qt generates image based PDFs when embedded fonts are present."
tickets: [1053906]
- title: "MTP windows driver: Do not try to connect to unsuitable devices such as the iPhone."
tickets: [1054562]
- title: "KF8 Input: Handle files that use non ascii paths/anchor names in the guide entries."
tickets: [1053751]
new recipes:
- title: Pubblico Giornale
author: iusvar
improved recipes:
- Monitor Online
- El Pais
- Chronicle of Higher Education
- Baltimore Sun
- Mac World
- Maximum PC
- Financial Times UK
- version: 0.8.70 - version: 0.8.70
date: 2012-09-21 date: 2012-09-21

View File

@ -59,10 +59,10 @@
<a href="http://calibre-ebook.com"><img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/></a> <a href="http://calibre-ebook.com"><img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/></a>
</p> </p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post"> <form action="https://www.paypal.com/cgi-bin/webscr" method="post" title="Contribute to support calibre development">
<input type="hidden" name="cmd" value="_s-xclick" /> <input type="hidden" name="cmd" value="_s-xclick" />
<input type="hidden" name="hosted_button_id" value="AF4H3B8QVDG6N" /> <input type="hidden" name="hosted_button_id" value="AF4H3B8QVDG6N" />
<input type="image" src="http://manual.calibre-ebook.com/simple_donate_button.gif" border="0" name="submit" alt="Donate to support calibre development" style="border:0pt" /> <input type="image" src="http://manual.calibre-ebook.com/simple_donate_button.gif" border="0" name="submit" alt="Contribute to support calibre development" style="border:0pt" />
<img alt="" border="0" src="https://www.paypalobjects.com/en_GB/i/scr/pixel.gif" width="1" height="1" /> <img alt="" border="0" src="https://www.paypalobjects.com/en_GB/i/scr/pixel.gif" width="1" height="1" />
</form> </form>
<hr/> <hr/>

View File

@ -1,45 +1,37 @@
from __future__ import with_statement from __future__ import with_statement
__license__ = 'GPL 3' __license__ = 'GPL 3'
__copyright__ = 'Original 2009, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__copyright__= 'Modified 2011, Josh Hall <jwtheiv@gmail.com>' __copyright__ = '2012 Josh Hall<jwtheiv@gmail.com>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
''' import urllib, re
www.baltimoresun.com
'''
from calibre.web.feeds.news import BasicNewsRecipe from calibre.web.feeds.news import BasicNewsRecipe
class BaltimoreSun(BasicNewsRecipe): class BaltimoreSun(BasicNewsRecipe):
title = 'The Baltimore Sun' title = 'The Baltimore Sun'
__author__ = 'Josh Hall' __author__ = 'Josh Hall'
description = 'Politics, local and business news from Baltimore'
description = 'Complete local news and blogs from Baltimore'
language = 'en' language = 'en'
version = 2
oldest_article = 1 oldest_article = 1
max_articles_per_feed = 100 max_articles_per_feed = 100
remove_empty_feeds = True
use_embedded_content = False use_embedded_content = False
no_stylesheets = True no_stylesheets = True
remove_javascript = True remove_javascript = True
#masthead_url = 'http://www.baltimoresun.com/images/thirdpartylogo.gif' recursions = 1
remove_tags_before = dict(name='div', attrs={'class':['story', 'entry']})
remove_tags_after = [
{'class':['photo_article',]},
dict(name='div', attrs={'class':'shirttail-promo right clearfix'}),
]
keep_only_tags = [dict(name='div', attrs={'class':["story","entry-asset asset hentry"]}), keep_only_tags = [dict(name='div', attrs={'class':["story","entry-asset asset hentry"]}),
dict(name='div', attrs={'id':["pagebody","story","maincontentcontainer"]}), dict(name='div', attrs={'id':["pagebody","story","maincontentcontainer"]}),
] ]
remove_tags_after = [{'class':['photo_article',]}]
match_regexps = [r'page=[0-9]+']
remove_tags = [{'id':["moduleArticleTools","content-bottom","rail","articleRelates module","toolSet","relatedrailcontent","div-wrapper","beta","atp-comments","footer","article-promo"]}, remove_tags = [{'id':["moduleArticleTools","content-bottom","rail","articleRelates module","toolSet","relatedrailcontent","div-wrapper","beta","atp-comments","footer",'gallery-subcontent','subFooter']},
{'class':["entry-footer-left","entry-footer-right","shirttail-promo right clearfix","clearfix","relatedTitle","articleRelates module","asset-footer","tools","comments","featurePromo","featurePromo fp-topjobs brownBackground","clearfix fullSpan brownBackground","curvedContent","toppaginate","module","module-header","module-content"]}, {'class':["clearfix","relatedTitle","articleRelates module","asset-footer","tools","comments","featurePromo","featurePromo fp-topjobs brownBackground","clearfix fullSpan brownBackground","curvedContent",'nextgen-share-tools','outbrainTools', 'google-ad-story-bottom']},
dict(name='font',attrs={'id':["cr-other-headlines"]}), dict(name='font',attrs={'id':["cr-other-headlines"]})]
dict(name=['iframe']),
]
extra_css = ''' extra_css = '''
h1{font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:large;} h1{font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:large;}
h2{font-family:Arial,Helvetica,sans-serif; font-weight:normal;font-size:small;} h2{font-family:Arial,Helvetica,sans-serif; font-weight:normal;font-size:small;}
@ -55,6 +47,7 @@ class BaltimoreSun(BasicNewsRecipe):
body{font-family:Helvetica,Arial,sans-serif;font-size:small;} body{font-family:Helvetica,Arial,sans-serif;font-size:small;}
''' '''
feeds = [ feeds = [
## News ##
(u'Top Headlines', u'http://www.baltimoresun.com/rss2.0.xml'), (u'Top Headlines', u'http://www.baltimoresun.com/rss2.0.xml'),
(u'Breaking News', u'http://www.baltimoresun.com/news/breaking/rss2.0.xml'), (u'Breaking News', u'http://www.baltimoresun.com/news/breaking/rss2.0.xml'),
(u'Top Maryland', u'http://www.baltimoresun.com/news/maryland/rss2.0.xml'), (u'Top Maryland', u'http://www.baltimoresun.com/news/maryland/rss2.0.xml'),
@ -69,10 +62,10 @@ class BaltimoreSun(BasicNewsRecipe):
(u'Local Politics', u'http://www.baltimoresun.com/news/maryland/politics/rss2.0.xml'), (u'Local Politics', u'http://www.baltimoresun.com/news/maryland/politics/rss2.0.xml'),
(u'Weather', u'http://www.baltimoresun.com/news/weather/rss2.0.xml'), (u'Weather', u'http://www.baltimoresun.com/news/weather/rss2.0.xml'),
#(u'Traffic', u'http://www.baltimoresun.com/features/commuting/rss2.0.xml'), #(u'Traffic', u'http://www.baltimoresun.com/features/commuting/rss2.0.xml'),
(u'Nation/world', u'http://feeds.chicagotribune.com/chicagotribune/news/nationworld/'), (u'Nation/world', u'http://feeds.feedburner.com/baltimoresun/news/nationworld/rss2'),
(u'Weird News', u'http://www.baltimoresun.com/news/offbeat/rss2.0.xml'), (u'Weird News', u'http://www.baltimoresun.com/news/offbeat/rss2.0.xml'),
##Sports##
(u'Top Sports', u'http://www.baltimoresun.com/sports/rss2.0.xml'), (u'Top Sports', u'http://www.baltimoresun.com/sports/rss2.0.xml'),
(u'Orioles/Baseball', u'http://www.baltimoresun.com/sports/orioles/rss2.0.xml'), (u'Orioles/Baseball', u'http://www.baltimoresun.com/sports/orioles/rss2.0.xml'),
(u'Ravens/Football', u'http://www.baltimoresun.com/sports/ravens/rss2.0.xml'), (u'Ravens/Football', u'http://www.baltimoresun.com/sports/ravens/rss2.0.xml'),
@ -85,6 +78,7 @@ class BaltimoreSun(BasicNewsRecipe):
#(u'High School', u'http://www.baltimoresun.com/sports/high-school/rss2.0.xml'), #(u'High School', u'http://www.baltimoresun.com/sports/high-school/rss2.0.xml'),
#(u'Outdoors', u'http://www.baltimoresun.com/sports/outdoors/rss2.0.xml'), #(u'Outdoors', u'http://www.baltimoresun.com/sports/outdoors/rss2.0.xml'),
## Entertainment ##
(u'Celebrity News', u'http://www.baltimoresun.com/entertainment/celebrities/rss2.0.xml'), (u'Celebrity News', u'http://www.baltimoresun.com/entertainment/celebrities/rss2.0.xml'),
(u'Arts & Theater', u'http://www.baltimoresun.com/entertainment/arts/rss2.0.xml'), (u'Arts & Theater', u'http://www.baltimoresun.com/entertainment/arts/rss2.0.xml'),
(u'Movies', u'http://www.baltimoresun.com/entertainment/movies/rss2.0.xml'), (u'Movies', u'http://www.baltimoresun.com/entertainment/movies/rss2.0.xml'),
@ -92,14 +86,16 @@ class BaltimoreSun(BasicNewsRecipe):
(u'Restaurants & Food', u'http://www.baltimoresun.com/entertainment/dining/rss2.0.xml'), (u'Restaurants & Food', u'http://www.baltimoresun.com/entertainment/dining/rss2.0.xml'),
(u'TV/Media', u'http://www.baltimoresun.com/entertainment/tv/rss2.0.xml'), (u'TV/Media', u'http://www.baltimoresun.com/entertainment/tv/rss2.0.xml'),
## Life ##
(u'Health&Wellness', u'http://www.baltimoresun.com/health/rss2.0.xml'), (u'Health&Wellness', u'http://www.baltimoresun.com/health/rss2.0.xml'),
(u'Home & Garden', u'http://www.baltimoresun.com/features/home-garden/rss2.0.xml'), (u'Home & Garden', u'http://www.baltimoresun.com/features/home-garden/rss2.0.xml'),
(u'Living Green', u'http://www.baltimoresun.com/features/green/rss2.0.xml'), (u'Living Green', u'http://www.baltimoresun.com/features/green/rss2.0.xml'),
(u'Parenting', u'http://www.baltimoresun.com/features/parenting/rss2.0.xml'), (u'Parenting', u'http://www.baltimoresun.com/features/parenting/rss2.0.xml'),
(u'Fashion', u'http://www.baltimoresun.com/features/fashion/rss2.0.xml'), (u'Fashion', u'http://www.baltimoresun.com/features/fashion/rss2.0.xml'),
(u'Travel', u'http://www.baltimoresun.com/travel/rss2.0.xml'), (u'Travel', u'http://www.baltimoresun.com/travel/rss2.0.xml'),
(u'Faith', u'http://www.baltimoresun.com/features/faith/rss2.0.xml'), #(u'Faith', u'http://www.baltimoresun.com/features/faith/rss2.0.xml'),
## Business ##
(u'Top Business', u'http://www.baltimoresun.com/business/rss2.0.xml'), (u'Top Business', u'http://www.baltimoresun.com/business/rss2.0.xml'),
(u'Technology', u'http://www.baltimoresun.com/business/technology/rss2.0.xml'), (u'Technology', u'http://www.baltimoresun.com/business/technology/rss2.0.xml'),
(u'Personal finance', u'http://www.baltimoresun.com/business/money/rss2.0.xml'), (u'Personal finance', u'http://www.baltimoresun.com/business/money/rss2.0.xml'),
@ -109,12 +105,14 @@ class BaltimoreSun(BasicNewsRecipe):
(u'Consumer Safety', u'http://www.baltimoresun.com/business/consumer-safety/rss2.0.xml'), (u'Consumer Safety', u'http://www.baltimoresun.com/business/consumer-safety/rss2.0.xml'),
(u'Investing', u'http://www.baltimoresun.com/business/money/rss2.0.xml'), (u'Investing', u'http://www.baltimoresun.com/business/money/rss2.0.xml'),
## Opinion##
(u'Sun Editorials', u'http://www.baltimoresun.com/news/opinion/editorial/rss2.0.xml'), (u'Sun Editorials', u'http://www.baltimoresun.com/news/opinion/editorial/rss2.0.xml'),
(u'Op/Ed', u'http://www.baltimoresun.com/news/opinion/oped/rss2.0.xml'), (u'Op/Ed', u'http://www.baltimoresun.com/news/opinion/oped/rss2.0.xml'),
(u'Readers Respond', u'http://www.baltimoresun.com/news/opinion/readersrespond/'), (u'Readers Respond', u'http://www.baltimoresun.com/news/opinion/readersrespond/'),
(u'Kevin Cowherd', 'http://www.baltimoresun.com/sports/bal-columnist-cowherd,0,6829726.columnist-rss2.0.xml'), ## Columnists ##
(u'Jay Hancock', u'http://www.baltimoresun.com/business/money/bal-columnist-hancock,0,6673611.columnist-rss2.0.xml'), (u'Kevin Cowherd', u'http://www.baltimoresun.com/sports/bal-columnist-cowherd,0,6829726.columnist-rss2.0.xml'),
(u'Robert Ehrlich', u'http://www.baltimoresun.com/news/opinion/columnists/bal-columnist-ehrlich,0,1825227.columnist-rss2.0.xml'),
(u'Jacques Kelly', u'http://www.baltimoresun.com/news/maryland/bal-columnist-kelly,0,1154701.columnist-rss2.0.xml'), (u'Jacques Kelly', u'http://www.baltimoresun.com/news/maryland/bal-columnist-kelly,0,1154701.columnist-rss2.0.xml'),
(u'Marta H. Mossburg', u'http://www.baltimoresun.com/news/opinion/oped/bal-columnist-mossburg,0,7982155.columnist-rss2.0.xml'), (u'Marta H. Mossburg', u'http://www.baltimoresun.com/news/opinion/oped/bal-columnist-mossburg,0,7982155.columnist-rss2.0.xml'),
(u'Mike Preston', u'http://www.baltimoresun.com/sports/bal-columnist-preston,0,6169796.columnist-rss2.0.xml'), (u'Mike Preston', u'http://www.baltimoresun.com/sports/bal-columnist-preston,0,6169796.columnist-rss2.0.xml'),
@ -122,59 +120,80 @@ class BaltimoreSun(BasicNewsRecipe):
(u'Dan Rodricks', u'http://www.baltimoresun.com/news/maryland/bal-columnist-rodricks,0,7089843.columnist-rss2.0.xml'), (u'Dan Rodricks', u'http://www.baltimoresun.com/news/maryland/bal-columnist-rodricks,0,7089843.columnist-rss2.0.xml'),
(u'Thomas F. Schaller', u'http://www.baltimoresun.com/news/opinion/columnists/bal-columnist-schaller,0,897397.columnist-rss2.0.xml'), (u'Thomas F. Schaller', u'http://www.baltimoresun.com/news/opinion/columnists/bal-columnist-schaller,0,897397.columnist-rss2.0.xml'),
(u'Peter Schmuck', u'http://www.baltimoresun.com/sports/bal-columnist-schmuck,0,7485088.columnist-rss2.0.xml'), (u'Peter Schmuck', u'http://www.baltimoresun.com/sports/bal-columnist-schmuck,0,7485088.columnist-rss2.0.xml'),
(u'Ron Smith', u'http://www.baltimoresun.com/news/opinion/bal-columnist-ronsmith,0,3964803.columnist-rss2.0.xml'),
(u'Baltimore Crime Beat', u'http://weblogs.baltimoresun.com/news/crime/blog/index.xml'), ## News Blogs ##
(u'Getting There', u'http://weblogs.baltimoresun.com/news/traffic/index.xml'), (u'Baltimore Crime Beat', u'http://baltimore.feedsportal.com/c/34255/f/623075/index.rss'),
(u'InsideEd', u'http://weblogs.baltimoresun.com/news/education/blog/index.xml'), (u'InsideEd', u'http://www.baltimoresun.com/news/maryland/education/blog/rss2.0.xml'),
(u'Maryland Politics', u'http://weblogs.baltimoresun.com/news/local/politics/index.xml'), (u'Maryland Politics', u'http://www.baltimoresun.com/news/maryland/politics/blog/rss2.0.xml'),
(u'Maryland Weather', u'http://weblogs.marylandweather.com/index.xml'), (u'Maryland Weather', u'http://www.baltimoresun.com/news/weather/weather-blog/rss2.0.xml'),
(u'Second Opinion', u'http://weblogs.baltimoresun.com/news/opinion/index.xml'), (u'Second Opinion', u'http://www.baltimoresun.com/news/opinion/second-opinion-blog/rss2.0.xml'),
(u'You Dont Say', u'http://weblogs.baltimoresun.com/news/mcintyre/blog/index.xml'), (u'Sun Investigates', u'http://www.baltimoresun.com/news/maryland/sun-investigates/rss2.0.xml'),
(u'You Dont Say', u'http://www.baltimoresun.com/news/language-blog/rss2.0.xml'),
(u'BaltTech', u'http://weblogs.baltimoresun.com/news/technology/index.xml'), ## Business Blogs ##
(u'Consuming Interests', u'http://weblogs.baltimoresun.com/business/consuminginterests/blog/index.xml'), (u'BaltTech', u'http://www.baltimoresun.com/business/technology/blog/rss2.0.xml'),
(u'Jay Hancocks Blog', u'http://weblogs.baltimoresun.com/business/hancock/blog/index.xml'), (u'Consuming Interests', u'http://www.baltimoresun.com/business/consuming-interests-blog/rss2.0.xml'),
(u'The Real Estate Wonk', u'http://weblogs.baltimoresun.com/business/realestate/blog/index.xml'), (u'The Real Estate Wonk', u'http://www.baltimoresun.com/business/real-estate/wonk/rss2.0.xml'),
(u'Clef Notes', 'http://weblogs.baltimoresun.com/entertainment/classicalmusic/index.xml'), ## Entertainment Blogs ##
(u'Dining at Large', u'http://weblogs.baltimoresun.com/entertainment/dining/reviews/blog/index.xml'), (u'Clef Notes & Drama Queens', 'http://weblogs.baltimoresun.com/entertainment/classicalmusic/index.xml'),
(u'Midnight Sun', u'http://weblogs.baltimoresun.com/entertainment/midnight_sun/blog/index.xml'), (u'Baltimore Diner', u'http://baltimore.feedsportal.com/c/34255/f/623088/index.rss'),
(u'Mike Sragow Gets Reel', u'http://weblogs.baltimoresun.com/entertainment/movies/blog/index.xml'), (u'Midnight Sun', u'http://www.baltimoresun.com/entertainment/music/midnight-sun-blog/rss2.0.xml'),
(u'Read Street', u'http://weblogs.baltimoresun.com/entertainment/books/blog/index.xml'), (u'Read Street', u'http://www.baltimoresun.com/features/books/read-street/rss2.0.xml'),
(u'Reality Check', u'http://weblogs.baltimoresun.com/entertainment/realitycheck/blog/index.xml'), (u'Z on TV', u'http://www.baltimoresun.com/entertainment/tv/z-on-tv-blog/rss2.0.xml'),
(u'Z on TV', u'http://weblogs.baltimoresun.com/entertainment/zontv/index.xml'),
## Life Blogs ##
(u'BMore Green', u'http://weblogs.baltimoresun.com/features/green/index.xml'), (u'BMore Green', u'http://weblogs.baltimoresun.com/features/green/index.xml'),
(u'Charm City Moms', u'http://weblogs.baltimoresun.com/features/baltimoremomblog/index.xml'), (u'Baltimore Insider',u'http://www.baltimoresun.com/features/baltimore-insider-blog/rss2.0.xml'),
(u'Exercists', u'http://weblogs.baltimoresun.com/health/fitness/index.xml'), (u'Homefront', u'http://www.baltimoresun.com/features/parenting/homefront/rss2.0.xml'),
(u'Garden Variety', 'http://weblogs.baltimoresun.com/features/gardening/index.xml'), (u'Picture of Health', u'http://www.baltimoresun.com/health/blog/rss2.0.xml'),
#(u'In Good Faith', u'http://weblogs.baltimoresun.com/news/faith/index.xml'),
(u'Picture of Health', u'http://weblogs.baltimoresun.com/health/index.xml'),
(u'Unleashed', u'http://weblogs.baltimoresun.com/features/mutts/blog/index.xml'), (u'Unleashed', u'http://weblogs.baltimoresun.com/features/mutts/blog/index.xml'),
## b the site blogs ##
(u'Game Cache', u'http://www.baltimoresun.com/entertainment/bthesite/game-cache/rss2.0.xml'),
(u'TV Lust', u'http://www.baltimoresun.com/entertainment/bthesite/tv-lust/rss2.0.xml'),
## Sports Blogs ##
(u'Baltimore Sports Blitz', u'http://baltimore.feedsportal.com/c/34255/f/623097/index.rss'),
#(u'Faceoff', u'http://weblogs.baltimoresun.com/sports/lacrosse/blog/index.xml'), #(u'Faceoff', u'http://weblogs.baltimoresun.com/sports/lacrosse/blog/index.xml'),
#(u'MMA Stomping Grounds', u'http://weblogs.baltimoresun.com/sports/mma/blog/index.xml'), #(u'MMA Stomping Grounds', u'http://weblogs.baltimoresun.com/sports/mma/blog/index.xml'),
(u'Orioles Insider', u'http://weblogs.baltimoresun.com/sports/orioles/blog/index.xml'), (u'Orioles Insider', u'http://baltimore.feedsportal.com/c/34255/f/623100/index.rss'),
#(u'Outdoors Girl', u'http://weblogs.baltimoresun.com/sports/outdoors/blog/index.xml'), (u'Ravens Insider', u'http://www.baltimoresun.com/sports/ravens/ravens-insider/rss2.0.xml'),
(u'Ravens Insider', u'http://weblogs.baltimoresun.com/sports/ravens/blog/index.xml'),
#(u'Recruiting Report', u'http://weblogs.baltimoresun.com/sports/college/recruiting/index.xml'), #(u'Recruiting Report', u'http://weblogs.baltimoresun.com/sports/college/recruiting/index.xml'),
#(u'Ring Posts', u'http://weblogs.baltimoresun.com/sports/wrestling/blog/index.xml'), #(u'Ring Posts', u'http://weblogs.baltimoresun.com/sports/wrestling/blog/index.xml'),
(u'The Schmuck Stops Here', u'http://weblogs.baltimoresun.com/sports/schmuck/index.xml'), (u'The Schmuck Stops Here', u'http://www.baltimoresun.com/sports/schmuck-blog/rss2.0.xml'),
(u'Toy Department', u'http://weblogs.baltimoresun.com/sports/thetoydepartment/index.xml'),
#(u'Tracking the Terps', u'http://weblogs.baltimoresun.com/sports/college/maryland_terps/blog/index.xml'), #(u'Tracking the Terps', u'http://weblogs.baltimoresun.com/sports/college/maryland_terps/blog/index.xml'),
#(u'Varsity Letters', u'http://weblogs.baltimoresun.com/sports/highschool/varsityletters/index.xml'), #(u'Varsity Letters', u'http://weblogs.baltimoresun.com/sports/highschool/varsityletters/index.xml'),
(u'Virtual Vensanity', u'http://weblogs.baltimoresun.com/entertainment/bthesite/vensel/index.xml'),
] ]
def get_article_url(self, article): def get_article_url(self, article):
print article.get('feedburner_origlink', article.get('guid', article.get('link'))) ans = None
return article.get('feedburner_origlink', article.get('guid', article.get('link'))) try:
s = article.summary
ans = urllib.unquote(
re.search(r'href=".+?bookmark.cfm.+?link=(.+?)"', s).group(1))
except:
pass
if ans is None:
ans = article.get('feedburner_origlink', article.get('guid', article.get('link')))
if ans is not None:
return ans.replace('?track=rss', '')
def skip_ad_pages(self, soup):
text = soup.find(text='click here to continue to article')
if text:
a = text.parent
url = a.get('href')
if url:
return self.index_to_soup(url, raw=True)
def postprocess_html(self, soup, first_fetch): def postprocess_html(self, soup, first_fetch):
# Remove the navigation bar. It was kept until now to be able to follow
# the links to further pages. But now we don't need them anymore.
for nav in soup.findAll(attrs={'class':['toppaginate','article-nav clearfix']}):
nav.extract()
for t in soup.findAll(['table', 'tr', 'td']): for t in soup.findAll(['table', 'tr', 'td']):
t.name = 'div' t.name = 'div'
@ -182,5 +201,3 @@ class BaltimoreSun(BasicNewsRecipe):
tag.extract() tag.extract()
for tag in soup.findAll('font', dict(attrs={'id':["cr-other-headlines"]})): for tag in soup.findAll('font', dict(attrs={'id':["cr-other-headlines"]})):
tag.extract() tag.extract()
return soup

View File

@ -1,3 +1,4 @@
import re
from calibre.web.feeds.recipes import BasicNewsRecipe from calibre.web.feeds.recipes import BasicNewsRecipe
from collections import OrderedDict from collections import OrderedDict
@ -14,7 +15,8 @@ class Chronicle(BasicNewsRecipe):
dict(name='div', attrs={'class':'article'}), dict(name='div', attrs={'class':'article'}),
] ]
remove_tags = [dict(name='div',attrs={'class':['related module1','maintitle']}), remove_tags = [dict(name='div',attrs={'class':['related module1','maintitle']}),
dict(name='div', attrs={'id':['section-nav','icon-row']})] dict(name='div', attrs={'id':['section-nav','icon-row', 'enlarge-popup']}),
dict(name='a', attrs={'class':'show-enlarge enlarge'})]
no_javascript = True no_javascript = True
no_stylesheets = True no_stylesheets = True
@ -31,7 +33,6 @@ class Chronicle(BasicNewsRecipe):
return br return br
def parse_index(self): def parse_index(self):
#Go to the issue #Go to the issue
soup0 = self.index_to_soup('http://chronicle.com/section/Archives/39/') soup0 = self.index_to_soup('http://chronicle.com/section/Archives/39/')
issue = soup0.find('ul',attrs={'class':'feature-promo-list'}).li issue = soup0.find('ul',attrs={'class':'feature-promo-list'}).li
@ -42,9 +43,12 @@ class Chronicle(BasicNewsRecipe):
self.timefmt = u' [%s]'%dates self.timefmt = u' [%s]'%dates
#Find cover #Find cover
cover=soup0.find('div',attrs={'class':'promo'}).findNext('div') cover=soup0.find('div',attrs={'class':'side-content'}).find(attrs={'src':re.compile("photos/biz/Current")})
self.cover_url="http://chronicle.com"+cover.find('img')['src'] if cover is not None:
if "chronicle.com" in cover['src']:
self.cover_url=cover['src']
else:
self.cover_url="http://chronicle.com" + cover['src']
#Go to the main body #Go to the main body
soup = self.index_to_soup(issueurl) soup = self.index_to_soup(issueurl)
div = soup.find ('div', attrs={'id':'article-body'}) div = soup.find ('div', attrs={'id':'article-body'})
@ -74,8 +78,10 @@ class Chronicle(BasicNewsRecipe):
def preprocess_html(self,soup): def preprocess_html(self,soup):
#process all the images #process all the images
for div in soup.findAll('div', attrs={'class':'tableauPlaceholder'}): for div in soup.findAll('div', attrs={'class':'tableauPlaceholder'}):
noscripts=div.find('noscript').a noscripts=div.find('noscript').a
div.replaceWith(noscripts) div.replaceWith(noscripts)
for div0 in soup.findAll('div',text='Powered by Tableau'): for div0 in soup.findAll('div',text='Powered by Tableau'):
div0.extract() div0.extract()
return soup return soup

View File

@ -41,7 +41,7 @@ class ElPais_RSS(BasicNewsRecipe):
,dict(attrs={'class':['firma','columna_texto','entrevista_p_r']}) ,dict(attrs={'class':['firma','columna_texto','entrevista_p_r']})
] ]
remove_tags = [ remove_tags = [
dict(name=['meta','link','base','iframe','embed','object']) dict(name=['iframe','embed','object'])
,dict(attrs={'class':'disposicion_vertical'}) ,dict(attrs={'class':'disposicion_vertical'})
] ]
@ -74,13 +74,14 @@ class ElPais_RSS(BasicNewsRecipe):
,(u'Justicia y Leyes' , u'http://elpais.com/tag/rss/justicia/a/' ) ,(u'Justicia y Leyes' , u'http://elpais.com/tag/rss/justicia/a/' )
,(u'Guerras y conflictos' , u'http://elpais.com/tag/rss/conflictos/a/' ) ,(u'Guerras y conflictos' , u'http://elpais.com/tag/rss/conflictos/a/' )
,(u'Politica' , u'http://ep00.epimg.net/rss/politica/portada.xml' ) ,(u'Politica' , u'http://ep00.epimg.net/rss/politica/portada.xml' )
,(u'Opinion' , u'http://ep01.epimg.net/rss/politica/opinion.xml' ) ,(u'Opinion' , u'http://ep01.epimg.net/rss/elpais/opinion.xml' )
] ]
def get_article_url(self, article): def get_article_url(self, article):
url = BasicNewsRecipe.get_article_url(self, article) url = BasicNewsRecipe.get_article_url(self, article)
if url and (not('/album/' in url) and not('/futbol/partido/' in url)): if url and (not('/album/' in url) and not('/futbol/partido/' in url)):
return url urlverified = self.browser.open_novisit(url).geturl()
return urlverified
self.log('Skipping non-article', url) self.log('Skipping non-article', url)
return None return None
@ -107,3 +108,7 @@ class ElPais_RSS(BasicNewsRecipe):
for item in soup.findAll('img',alt=False): for item in soup.findAll('img',alt=False):
item['alt'] = 'image' item['alt'] = 'image'
return soup return soup
def preprocess_raw_html(self, raw, url):
return '<html><head><title>Untitled</title>'+raw[raw.find('</head>'):]

View File

@ -1,5 +1,5 @@
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2010-2011, Darko Miletic <darko.miletic at gmail.com>' __copyright__ = '2010-2012, Darko Miletic <darko.miletic at gmail.com>'
''' '''
www.ft.com/uk-edition www.ft.com/uk-edition
''' '''
@ -55,6 +55,11 @@ class FinancialTimes(BasicNewsRecipe):
,dict(name='div' , attrs={'class':'standfirst'}) ,dict(name='div' , attrs={'class':'standfirst'})
,dict(name='div' , attrs={'id' :'storyContent'}) ,dict(name='div' , attrs={'id' :'storyContent'})
,dict(name='div' , attrs={'class':['ft-story-body','index-detail']}) ,dict(name='div' , attrs={'class':['ft-story-body','index-detail']})
,dict(name='div' , attrs={'class':['ft-story-body','index-detail']})
,dict(name='h2' , attrs={'class':'entry-title'} )
,dict(name='span', attrs={'class':lambda x: x and 'posted-on' in x.split()} )
,dict(name='span', attrs={'class':'author_byline'} )
,dict(name='div' , attrs={'class':'entry-content'} )
] ]
remove_tags = [ remove_tags = [
dict(name='div', attrs={'id':'floating-con'}) dict(name='div', attrs={'id':'floating-con'})
@ -83,9 +88,8 @@ class FinancialTimes(BasicNewsRecipe):
if self.test and count > 2: if self.test and count > 2:
return articles return articles
rawlink = item['href'] rawlink = item['href']
if rawlink.startswith('http://'):
url = rawlink url = rawlink
else: if not rawlink.startswith('http://'):
url = self.PREFIX + rawlink url = self.PREFIX + rawlink
urlverified = self.browser.open_novisit(url).geturl() # resolve redirect. urlverified = self.browser.open_novisit(url).geturl() # resolve redirect.
title = self.tag_to_string(item) title = self.tag_to_string(item)
@ -106,20 +110,20 @@ class FinancialTimes(BasicNewsRecipe):
wide = soup.find('div',attrs={'class':'wide'}) wide = soup.find('div',attrs={'class':'wide'})
if not wide: if not wide:
return feeds return feeds
strest = wide.findAll('h3', attrs={'class':'section'}) allsections = wide.findAll(attrs={'class':lambda x: x and 'footwell' in x.split()})
if not strest: if not allsections:
return feeds return feeds
st = wide.findAll('h4',attrs={'class':'section-no-arrow'})
if st:
st.extend(strest)
count = 0 count = 0
for item in st: for item in allsections:
count = count + 1 count = count + 1
if self.test and count > 2: if self.test and count > 2:
return feeds return feeds
ftitle = self.tag_to_string(item) fitem = item.h3
if not fitem:
fitem = item.h4
ftitle = self.tag_to_string(fitem)
self.report_progress(0, _('Fetching feed')+' %s...'%(ftitle)) self.report_progress(0, _('Fetching feed')+' %s...'%(ftitle))
feedarts = self.get_artlinks(item.parent.ul) feedarts = self.get_artlinks(item.ul)
feeds.append((ftitle,feedarts)) feeds.append((ftitle,feedarts))
return feeds return feeds
@ -166,7 +170,8 @@ class FinancialTimes(BasicNewsRecipe):
except: except:
print "Retrying download..." print "Retrying download..."
count += 1 count += 1
self.temp_files.append(PersistentTemporaryFile('_fa.html')) tfile = PersistentTemporaryFile('_fa.html')
self.temp_files[-1].write(html) tfile.write(html)
self.temp_files[-1].close() tfile.close()
return self.temp_files[-1].name self.temp_files.append(tfile)
return tfile.name

BIN
recipes/icons/monitor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -34,20 +34,21 @@ class macWorld(BasicNewsRecipe):
remove_javascript = True remove_javascript = True
no_stylesheets = True no_stylesheets = True
auto_cleanup = True
keep_only_tags = [ #keep_only_tags = [
dict(name='div', attrs={'id':'content'}) #dict(name='div', attrs={'id':'content'})
] #]
remove_tags = [ #remove_tags = [
{'class':['toolBar','mac_tags','toolBar btmTools','textAds']}, #{'class':['toolBar','mac_tags','toolBar btmTools','textAds']},
dict(name='p', attrs={'class':'breadcrumbs'}), #dict(name='p', attrs={'class':'breadcrumbs'}),
dict(id=['breadcrumb','sidebar','comments','topContentWrapper', #dict(id=['breadcrumb','sidebar','comments','topContentWrapper',
'rightColumn', 'aboveFootPromo', 'storyCarousel']), #'rightColumn', 'aboveFootPromo', 'storyCarousel']),
{'class':lambda x: x and ('tools' in x or 'toolBar' #{'class':lambda x: x and ('tools' in x or 'toolBar'
in x)} #in x)}
] #]
feeds = [ feeds = [
(u'MacWorld Headlines', u'http://rss.macworld.com/macworld/news'), (u'MacWorld Headlines', u'http://rss.macworld.com/macworld/news'),
@ -82,3 +83,4 @@ class macWorld(BasicNewsRecipe):
.articleInfo {color:#4D4D4D;font-family:Arial,Helvetica,sans-serif;font-size:10px; font-size-adjust:none; font-stretch:normal; font-style:bold; font-variant:normal; font-weight:bold; line-height:10px; text-decoration:none;} .articleInfo {color:#4D4D4D;font-family:Arial,Helvetica,sans-serif;font-size:10px; font-size-adjust:none; font-stretch:normal; font-style:bold; font-variant:normal; font-weight:bold; line-height:10px; text-decoration:none;}
img {align:left;} img {align:left;}
''' '''

View File

@ -1,4 +1,3 @@
from calibre.ptempfile import PersistentTemporaryFile
from calibre.web.feeds.news import BasicNewsRecipe from calibre.web.feeds.news import BasicNewsRecipe
class AdvancedUserRecipe1276930924(BasicNewsRecipe): class AdvancedUserRecipe1276930924(BasicNewsRecipe):
@ -14,30 +13,30 @@ class AdvancedUserRecipe1276930924(BasicNewsRecipe):
use_embedded_content = False use_embedded_content = False
no_stylesheets = True no_stylesheets = True
language = 'en' language = 'en'
temp_files = [] auto_cleanup = True
articles_are_obfuscated = True feeds = [#(u'News', u'http://www.maximumpc.com/articles/all/feed'),
feeds = [(u'News', u'http://www.maximumpc.com/articles/4/feed'), (u'News', u'http://www.maximumpc.com/articles/4/feed'),
(u'Reviews', u'http://www.maximumpc.com/articles/40/feed'), (u'Reviews', u'http://www.maximumpc.com/articles/40/feed'),
(u'Editors Blog', u'http://www.maximumpc.com/articles/6/feed'), (u'Editors Blog', u'http://www.maximumpc.com/articles/6/feed'),
(u'How-to', u'http://www.maximumpc.com/articles/32/feed'), (u'How-to', u'http://www.maximumpc.com/articles/32/feed'),
(u'Features', u'http://www.maximumpc.com/articles/31/feed'), (u'Features', u'http://www.maximumpc.com/articles/31/feed'),
(u'From the Magazine', u'http://www.maximumpc.com/articles/72/feed') (u'From the Magazine', u'http://www.maximumpc.com/articles/72/feed')
] ]
keep_only_tags = [ #keep_only_tags = [
dict(name='div', attrs={'class':['print-title','article_body']}), #dict(name='div', attrs={'class':['print-title','article_body']}),
] #]
remove_tags = [ #remove_tags = [
dict(name='div', attrs={'class':'comments-tags-actions'}), #dict(name='div', attrs={'class':'comments-tags-actions'}),
] #]
remove_tags_before = dict(name='div', attrs={'class':'print-title'}) #remove_tags_before = dict(name='div', attrs={'class':'print-title'})
remove_tags_after = dict(name='div', attrs={'class':'meta-content'}) #remove_tags_after = dict(name='div', attrs={'class':'meta-content'})
def get_obfuscated_article(self, url): #def get_obfuscated_article(self, url):
br = self.get_browser() #br = self.get_browser()
br.open(url) #br.open(url)
response = br.follow_link(url_regex = r'/print/[0-9]+', nr = 0) #response = br.follow_link(url_regex = r'/print/[0-9]+', nr = 0)
html = response.read() #html = response.read()
self.temp_files.append(PersistentTemporaryFile('_fa.html')) #self.temp_files.append(PersistentTemporaryFile('_fa.html'))
self.temp_files[-1].write(html) #self.temp_files[-1].write(html)
self.temp_files[-1].close() #self.temp_files[-1].close()
return self.temp_files[-1].name #return self.temp_files[-1].name

View File

@ -1,99 +1,66 @@
#!/usr/bin/env python
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>' __copyright__ = '2009-2012, Darko Miletic <darko.miletic at gmail.com>'
''' '''
monitorcg.com www.monitor.co.me
''' '''
import re import re
from calibre.web.feeds.news import BasicNewsRecipe from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import Tag
class MonitorCG(BasicNewsRecipe): class MonitorCG(BasicNewsRecipe):
title = 'Monitor online' title = 'MONITOR online'
__author__ = 'Darko Miletic' __author__ = 'Darko Miletic'
description = 'News from Montenegro' description = 'Nezavisni nedjeljnik Monitor'
publisher = 'MONITOR d.o.o. Podgorica' publisher = '"Monitor" D.O.O. Podgorica'
category = 'news, politics, Montenegro' category = 'news, politics, Montenegro'
oldest_article = 15 oldest_article = 15
max_articles_per_feed = 150 max_articles_per_feed = 150
no_stylesheets = True no_stylesheets = True
encoding = 'utf-8' encoding = 'utf-8'
auto_cleanup = False
use_embedded_content = False use_embedded_content = False
language = 'sr' language = 'sr'
remove_empty_feeds = True
lang ='sr-Latn-Me' extra_css = """
INDEX = 'http://www.monitorcg.com' @font-face {font-family: "serif1";src:url(res:///opt/sony/ebook/FONT/tt0011m_.ttf)}
@font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)}
extra_css = ' @font-face {font-family: "serif1";src:url(res:///opt/sony/ebook/FONT/tt0011m_.ttf)} body{font-family: serif1, serif} ' h2{font-family: Cambria,"Times New Roman",Times,serif1,serif}
body{font-family: Arial,sans1,sans-serif}
img{display: block}
"""
conversion_options = { conversion_options = {
'comment' : description 'comment' : description
, 'tags' : category , 'tags' : category
, 'publisher' : publisher , 'publisher' : publisher
, 'language' : lang , 'language' : language
, 'pretty_print': True , 'pretty_print': True
} }
preprocess_regexps = [(re.compile(u'\u0110'), lambda match: u'\u00D0')] preprocess_regexps = [(re.compile(u'\u0110'), lambda match: u'\u00D0')]
keep_only_tags = [dict(attrs={'class':['contentheading','article-meta','article-content']})]
remove_attributes = ['width','height','font','border','align']
keep_only_tags = [dict(name='div', attrs={'id':'ja-current-content'})] feeds = [
(u'Danas, Sjutra' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=5&Itemid=27&format=feed&type=rss')
remove_tags = [ dict(name=['object','link','embed']) ,(u'Duhankesa' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=13&Itemid=37&format=feed&type=rss')
, dict(attrs={'class':['buttonheading','article-section']})] ,(u'Znaci prepoznavanja', u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=6&Itemid=358&format=feed&type=rss')
,(u'Paralele' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=8&Itemid=359&format=feed&type=rss')
remove_attributes = ['style','width','height','font','border','align'] ,(u'Razbijeno ogledalo' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=18&Itemid=354&format=feed&type=rss')
,(u'Tržište' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=26&Itemid=371&format=feed&type=rss')
def adeify_images2(cls, soup): ,(u'Feljton' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=29&Itemid=471&format=feed&type=rss')
for item in soup.findAll('img'): ,(u'Monitor' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=1&Itemid=1852&format=feed&type=rss')
for attrib in ['height','width','border','align','style']: ,(u'Altervizija' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=31&Itemid=2623&format=feed&type=rss')
if item.has_key(attrib): ,(u'Fenomeni' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=35&Itemid=3549&format=feed&type=rss')
del item[attrib] ,(u'Fokus' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=19&Itemid=252&format=feed&type=rss')
oldParent = item.parent ,(u'Monitoring' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=19&Itemid=252&format=feed&type=rss')
if oldParent.name == 'a': ,(u'Profil' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=21&Itemid=256&format=feed&type=rss')
oldParent.name == 'p' ,(u'Intervju' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=27&Itemid=404&format=feed&type=rss')
myIndex = oldParent.contents.index(item) ,(u'Društvo' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=14&Itemid=2&format=feed&type=rss')
brtag = Tag(soup,'br') ,(u'Region' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=12&Itemid=53&format=feed&type=rss')
oldParent.insert(myIndex+1,brtag) ,(u'Svijet' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=11&Itemid=360&format=feed&type=rss')
return soup ,(u'Kultura' , u'http://www.monitor.co.me/index.php?option=com_content&view=section&layout=blog&id=9&Itemid=361&format=feed&type=rss')
]
def preprocess_html(self, soup):
soup.html['xml:lang'] = self.lang
soup.html['lang'] = self.lang
mlang = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.lang)])
soup.html.insert(0,mlang)
return self.adeify_images2(soup)
def parse_index(self):
totalfeeds = []
soup = self.index_to_soup(self.INDEX)
cover_item = soup.find('div',attrs={'class':'ja-catslwi'})
if cover_item:
dt = cover_item['onclick'].partition("location.href=")[2]
curl = self.INDEX + dt.strip("'")
lfeeds = [(u'Svi clanci', curl)]
for feedobj in lfeeds:
feedtitle, feedurl = feedobj
self.report_progress(0, _('Fetching feed')+' %s...'%(feedtitle if feedtitle else feedurl))
articles = []
soup = self.index_to_soup(feedurl)
contitem = soup.find('div',attrs={'class':'article-content'})
if contitem:
img = contitem.find('img')
if img:
self.cover_url = self.INDEX + img['src']
for item in contitem.findAll('a'):
url = self.INDEX + item['href']
title = self.tag_to_string(item)
articles.append({
'title' :title
,'date' :''
,'url' :url
,'description':''
})
totalfeeds.append((feedtitle, articles))
return totalfeeds

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
__license__ = 'GPL v3'
__author__ = 'iusvar'
__description__ = 'Pubblico giornale'
'''
http://pubblicogiornale.it/
'''
from calibre.web.feeds.news import BasicNewsRecipe
class Pubblicogiornale(BasicNewsRecipe):
description = 'Italian newspaper directed by Luca Telese'
cover_url = 'http://pubblicogiornale.it/wp-content/uploads/logo_n.png?84cd58'
title = u'Pubblico giornale'
publisher = 'PUBBLICO EDIZIONI Srl'
category = 'News'
language = 'it'
__author__ = 'iusvar'
feeds = [(u'Pubblico giornale', u'http://pubblicogiornale.it/feed/')]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@ -6,7 +6,7 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import sys, os, shutil, glob, py_compile, subprocess, re, zipfile, time import sys, os, shutil, glob, py_compile, subprocess, re, zipfile, time, textwrap
from setup import (Command, modules, functions, basenames, __version__, from setup import (Command, modules, functions, basenames, __version__,
__appname__) __appname__)
@ -407,7 +407,7 @@ class Win32Freeze(Command, WixMixIn):
cmd = [msvc.linker] + ['/INCREMENTAL:NO', '/MACHINE:X86', cmd = [msvc.linker] + ['/INCREMENTAL:NO', '/MACHINE:X86',
'/LIBPATH:'+self.obj_dir, '/SUBSYSTEM:WINDOWS', '/LIBPATH:'+self.obj_dir, '/SUBSYSTEM:WINDOWS',
'/LIBPATH:'+(LZMA+r'\lib\Release'), '/LIBPATH:'+(LZMA+r'\lib\Release'),
'/RELEASE', '/RELEASE', '/MANIFEST', '/MANIFESTUAC:level="asInvoker" uiAccess="false"',
'/ENTRY:wWinMainCRTStartup', '/ENTRY:wWinMainCRTStartup',
'/OUT:'+exe, self.embed_resources(exe, '/OUT:'+exe, self.embed_resources(exe,
desc='Calibre Portable Installer', extra_data=zf, desc='Calibre Portable Installer', extra_data=zf,
@ -415,6 +415,31 @@ class Win32Freeze(Command, WixMixIn):
xobj, obj, 'User32.lib', 'Shell32.lib', 'easylzma_s.lib', xobj, obj, 'User32.lib', 'Shell32.lib', 'easylzma_s.lib',
'Ole32.lib', 'Shlwapi.lib', 'Kernel32.lib', 'Psapi.lib'] 'Ole32.lib', 'Shlwapi.lib', 'Kernel32.lib', 'Psapi.lib']
self.run_builder(cmd) self.run_builder(cmd)
manifest = exe + '.manifest'
with open(manifest, 'r+b') as f:
raw = f.read()
f.seek(0)
f.truncate()
# TODO: Add the windows 8 GUID to the compatibility section
# after windows 8 is released, see:
# http://msdn.microsoft.com/en-us/library/windows/desktop/hh848036(v=vs.85).aspx
raw = raw.replace(b'</assembly>', textwrap.dedent(
b'''\
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--The ID below indicates app support for Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!--The ID below indicates app support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
</application>
</compatibility>
</assembly>
'''))
f.write(raw)
self.run_builder([MT, '-manifest', manifest,
'-outputresource:%s;1'%exe])
os.remove(manifest)
os.remove(zf) os.remove(zf)

View File

@ -9,33 +9,33 @@ msgstr ""
"Report-Msgid-Bugs-To: Debian iso-codes team <pkg-isocodes-" "Report-Msgid-Bugs-To: Debian iso-codes team <pkg-isocodes-"
"devel@lists.alioth.debian.org>\n" "devel@lists.alioth.debian.org>\n"
"POT-Creation-Date: 2011-11-25 14:01+0000\n" "POT-Creation-Date: 2011-11-25 14:01+0000\n"
"PO-Revision-Date: 2011-11-12 07:52+0000\n" "PO-Revision-Date: 2012-09-25 20:15+0000\n"
"Last-Translator: Devilinside <Unknown>\n" "Last-Translator: Gergely Szarka <szarka.honved@gmail.com>\n"
"Language-Team: Hungarian <debian-l10n-hungarian@lists.d.o>\n" "Language-Team: Hungarian <debian-l10n-hungarian@lists.d.o>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-11-26 05:19+0000\n" "X-Launchpad-Export-Date: 2012-09-26 04:36+0000\n"
"X-Generator: Launchpad (build 14381)\n" "X-Generator: Launchpad (build 16022)\n"
"X-Poedit-Country: HUNGARY\n" "X-Poedit-Country: HUNGARY\n"
"Language: hu\n" "Language: hu\n"
"X-Poedit-Language: Hungarian\n" "X-Poedit-Language: Hungarian\n"
#. name for aaa #. name for aaa
msgid "Ghotuo" msgid "Ghotuo"
msgstr "ghotuo" msgstr "Ghotuo"
#. name for aab #. name for aab
msgid "Alumu-Tesu" msgid "Alumu-Tesu"
msgstr "alumu-tesu" msgstr "Alumu-Tesu"
#. name for aac #. name for aac
msgid "Ari" msgid "Ari"
msgstr "ari" msgstr "Ari"
#. name for aad #. name for aad
msgid "Amal" msgid "Amal"
msgstr "amal" msgstr "Amal"
#. name for aae #. name for aae
msgid "Albanian; Arbëreshë" msgid "Albanian; Arbëreshë"
@ -43,11 +43,11 @@ msgstr "albán; Arbëreshë"
#. name for aaf #. name for aaf
msgid "Aranadan" msgid "Aranadan"
msgstr "aranadan" msgstr "Aranadan"
#. name for aag #. name for aag
msgid "Ambrak" msgid "Ambrak"
msgstr "ambrak" msgstr "Ambrak"
#. name for aah #. name for aah
msgid "Arapesh; Abu'" msgid "Arapesh; Abu'"
@ -55,11 +55,11 @@ msgstr "arapesh; Abu'"
#. name for aai #. name for aai
msgid "Arifama-Miniafia" msgid "Arifama-Miniafia"
msgstr "arifama-miniafia" msgstr "Arifama-Miniafia"
#. name for aak #. name for aak
msgid "Ankave" msgid "Ankave"
msgstr "ankave" msgstr "Ankave"
#. name for aal #. name for aal
msgid "Afade" msgid "Afade"
@ -107,11 +107,11 @@ msgstr "szolong"
#. name for aax #. name for aax
msgid "Mandobo Atas" msgid "Mandobo Atas"
msgstr "" msgstr "Mandobo Atas"
#. name for aaz #. name for aaz
msgid "Amarasi" msgid "Amarasi"
msgstr "" msgstr "Amarasi"
#. name for aba #. name for aba
msgid "Abé" msgid "Abé"
@ -119,7 +119,7 @@ msgstr "abé"
#. name for abb #. name for abb
msgid "Bankon" msgid "Bankon"
msgstr "" msgstr "Bankon"
#. name for abc #. name for abc
msgid "Ayta; Ambala" msgid "Ayta; Ambala"
@ -127,7 +127,7 @@ msgstr ""
#. name for abd #. name for abd
msgid "Manide" msgid "Manide"
msgstr "" msgstr "Manide"
#. name for abe #. name for abe
msgid "Abnaki; Western" msgid "Abnaki; Western"
@ -135,11 +135,11 @@ msgstr "abnaki; nyugati"
#. name for abf #. name for abf
msgid "Abai Sungai" msgid "Abai Sungai"
msgstr "" msgstr "Abai Sungai"
#. name for abg #. name for abg
msgid "Abaga" msgid "Abaga"
msgstr "" msgstr "Abaga"
#. name for abh #. name for abh
msgid "Arabic; Tajiki" msgid "Arabic; Tajiki"
@ -147,7 +147,7 @@ msgstr "arab; tadzsik"
#. name for abi #. name for abi
msgid "Abidji" msgid "Abidji"
msgstr "" msgstr "Abidji"
#. name for abj #. name for abj
msgid "Aka-Bea" msgid "Aka-Bea"
@ -159,19 +159,19 @@ msgstr "abház"
#. name for abl #. name for abl
msgid "Lampung Nyo" msgid "Lampung Nyo"
msgstr "" msgstr "Lampung Nyo"
#. name for abm #. name for abm
msgid "Abanyom" msgid "Abanyom"
msgstr "" msgstr "Abanyom"
#. name for abn #. name for abn
msgid "Abua" msgid "Abua"
msgstr "" msgstr "Abua"
#. name for abo #. name for abo
msgid "Abon" msgid "Abon"
msgstr "" msgstr "Abon"
#. name for abp #. name for abp
msgid "Ayta; Abellen" msgid "Ayta; Abellen"
@ -179,11 +179,11 @@ msgstr ""
#. name for abq #. name for abq
msgid "Abaza" msgid "Abaza"
msgstr "" msgstr "Abaza"
#. name for abr #. name for abr
msgid "Abron" msgid "Abron"
msgstr "" msgstr "Abron"
#. name for abs #. name for abs
msgid "Malay; Ambonese" msgid "Malay; Ambonese"
@ -191,11 +191,11 @@ msgstr "maláj; amboni"
#. name for abt #. name for abt
msgid "Ambulas" msgid "Ambulas"
msgstr "" msgstr "Ambulas"
#. name for abu #. name for abu
msgid "Abure" msgid "Abure"
msgstr "" msgstr "Abure"
#. name for abv #. name for abv
msgid "Arabic; Baharna" msgid "Arabic; Baharna"
@ -203,31 +203,31 @@ msgstr "arab; Baharna"
#. name for abw #. name for abw
msgid "Pal" msgid "Pal"
msgstr "" msgstr "Pal"
#. name for abx #. name for abx
msgid "Inabaknon" msgid "Inabaknon"
msgstr "" msgstr "Inabaknon"
#. name for aby #. name for aby
msgid "Aneme Wake" msgid "Aneme Wake"
msgstr "" msgstr "Aneme Wake"
#. name for abz #. name for abz
msgid "Abui" msgid "Abui"
msgstr "" msgstr "Abui"
#. name for aca #. name for aca
msgid "Achagua" msgid "Achagua"
msgstr "" msgstr "Achagua"
#. name for acb #. name for acb
msgid "Áncá" msgid "Áncá"
msgstr "" msgstr "Áncá"
#. name for acd #. name for acd
msgid "Gikyode" msgid "Gikyode"
msgstr "" msgstr "Gikyode"
# src/trans.h:220 # src/trans.h:220
#. name for ace #. name for ace
@ -244,15 +244,15 @@ msgstr "acoli"
#. name for aci #. name for aci
msgid "Aka-Cari" msgid "Aka-Cari"
msgstr "" msgstr "Aka-Cari"
#. name for ack #. name for ack
msgid "Aka-Kora" msgid "Aka-Kora"
msgstr "" msgstr "Aka-Kora"
#. name for acl #. name for acl
msgid "Akar-Bale" msgid "Akar-Bale"
msgstr "" msgstr "Akar-Bale"
#. name for acm #. name for acm
msgid "Arabic; Mesopotamian" msgid "Arabic; Mesopotamian"
@ -264,7 +264,7 @@ msgstr ""
#. name for acp #. name for acp
msgid "Acipa; Eastern" msgid "Acipa; Eastern"
msgstr "" msgstr "Acipa; Keleti"
#. name for acq #. name for acq
msgid "Arabic; Ta'izzi-Adeni" msgid "Arabic; Ta'izzi-Adeni"
@ -272,7 +272,7 @@ msgstr "arabic; ta'izzi-adeni"
#. name for acr #. name for acr
msgid "Achi" msgid "Achi"
msgstr "" msgstr "Achi"
#. name for acs #. name for acs
msgid "Acroá" msgid "Acroá"

View File

@ -4,7 +4,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__ = u'calibre' __appname__ = u'calibre'
numeric_version = (0, 8, 70) numeric_version = (0, 9, 0)
__version__ = u'.'.join(map(unicode, numeric_version)) __version__ = u'.'.join(map(unicode, numeric_version))
__author__ = u"Kovid Goyal <kovid@kovidgoyal.net>" __author__ = u"Kovid Goyal <kovid@kovidgoyal.net>"

View File

@ -230,7 +230,7 @@ class ANDROID(USBMS):
'THINKPAD_TABLET', 'SGH-T989', 'YP-G70', 'STORAGE_DEVICE', 'THINKPAD_TABLET', 'SGH-T989', 'YP-G70', 'STORAGE_DEVICE',
'ADVANCED', 'SGH-I727', 'USB_FLASH_DRIVER', 'ANDROID', 'ADVANCED', 'SGH-I727', 'USB_FLASH_DRIVER', 'ANDROID',
'S5830I_CARD', 'MID7042', 'LINK-CREATE', '7035', 'VIEWPAD_7E', 'S5830I_CARD', 'MID7042', 'LINK-CREATE', '7035', 'VIEWPAD_7E',
'NOVO7'] 'NOVO7', 'MB526']
WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897', WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897',
'FILE-STOR_GADGET', 'SGH-T959_CARD', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD', 'FILE-STOR_GADGET', 'SGH-T959_CARD', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD',
'A70S', 'A101IT', '7', 'INCREDIBLE', 'A7EB', 'SGH-T849_CARD', 'A70S', 'A101IT', '7', 'INCREDIBLE', 'A7EB', 'SGH-T849_CARD',

View File

@ -288,7 +288,7 @@ class KINDLE2(KINDLE):
name = 'Kindle 2/3/4/Touch Device Interface' name = 'Kindle 2/3/4/Touch Device Interface'
description = _('Communicate with the Kindle 2/3/4/Touch eBook reader.') description = _('Communicate with the Kindle 2/3/4/Touch eBook reader.')
FORMATS = ['azw3'] + KINDLE.FORMATS + ['pdf', 'azw4', 'pobi'] FORMATS = ['azw', 'mobi', 'azw3', 'prc', 'azw1', 'tpz', 'azw4', 'pobi', 'pdf', 'txt']
DELETE_EXTS = KINDLE.DELETE_EXTS + ['.mbp1', '.mbs', '.sdr', '.han'] DELETE_EXTS = KINDLE.DELETE_EXTS + ['.mbp1', '.mbs', '.sdr', '.han']
# On the Touch, there's also .asc files, but not using the same basename (for X-Ray & End Actions), azw3f & azw3r files, but all of them are in the .sdr sidecar folder # On the Touch, there's also .asc files, but not using the same basename (for X-Ray & End Actions), azw3f & azw3r files, but all of them are in the .sdr sidecar folder
@ -450,7 +450,7 @@ class KINDLE_DX(KINDLE2):
name = 'Kindle DX Device Interface' name = 'Kindle DX Device Interface'
description = _('Communicate with the Kindle DX eBook reader.') description = _('Communicate with the Kindle DX eBook reader.')
FORMATS = KINDLE2.FORMATS[1:] FORMATS = ['azw', 'mobi', 'prc', 'azw1', 'tpz', 'azw4', 'pobi', 'pdf', 'txt']
PRODUCT_ID = [0x0003] PRODUCT_ID = [0x0003]
BCD = [0x0100] BCD = [0x0100]
@ -462,7 +462,7 @@ class KINDLE_FIRE(KINDLE2):
name = 'Kindle Fire Device Interface' name = 'Kindle Fire Device Interface'
description = _('Communicate with the Kindle Fire') description = _('Communicate with the Kindle Fire')
gui_name = 'Fire' gui_name = 'Fire'
FORMATS = list(KINDLE2.FORMATS) FORMATS = ['azw3', 'azw', 'mobi', 'prc', 'azw1', 'tpz', 'azw4', 'pobi', 'pdf', 'txt']
PRODUCT_ID = [0x0006] PRODUCT_ID = [0x0006]
BCD = [0x216, 0x100] BCD = [0x216, 0x100]

View File

@ -169,6 +169,7 @@ class MTP_DEVICE(MTPDeviceBase):
try: try:
self.dev = self.create_device(connected_device) self.dev = self.create_device(connected_device)
except Exception as e: except Exception as e:
self.blacklisted_devices.add(connected_device)
raise OpenFailed('Failed to open %s: Error: %s'%( raise OpenFailed('Failed to open %s: Error: %s'%(
connected_device, as_unicode(e))) connected_device, as_unicode(e)))
@ -195,6 +196,19 @@ class MTP_DEVICE(MTPDeviceBase):
self.current_serial_num = snum self.current_serial_num = snum
self.currently_connected_dev = connected_device self.currently_connected_dev = connected_device
@synchronous
def device_debug_info(self):
ans = self.get_gui_name()
ans += '\nSerial number: %s'%self.current_serial_num
ans += '\nManufacturer: %s'%self.dev.manufacturer_name
ans += '\nModel: %s'%self.dev.model_name
ans += '\nids: %s'%(self.dev.ids,)
ans += '\nDevice version: %s'%self.dev.device_version
ans += '\nStorage:\n'
storage = sorted(self.dev.storage_info, key=operator.itemgetter('id'))
ans += pprint.pformat(storage)
return ans
@property @property
def filesystem_cache(self): def filesystem_cache(self):
if self._filesystem_cache is None: if self._filesystem_cache is None:

View File

@ -84,8 +84,8 @@ PyObject* get_storage_info(IPortableDevice *device) { // {{{
PWSTR object_ids[10]; PWSTR object_ids[10];
GUID guid; GUID guid;
ULONGLONG capacity, free_space, capacity_objects, free_objects; ULONGLONG capacity, free_space, capacity_objects, free_objects;
ULONG access; ULONG access, storage_type = WPD_STORAGE_TYPE_UNDEFINED;
LPWSTR storage_desc = NULL; LPWSTR storage_desc = NULL, st = NULL;
storage = PyList_New(0); storage = PyList_New(0);
if (storage == NULL) { PyErr_NoMemory(); goto end; } if (storage == NULL) { PyErr_NoMemory(); goto end; }
@ -116,6 +116,7 @@ PyObject* get_storage_info(IPortableDevice *device) { // {{{
hr = storage_properties->Add(WPD_STORAGE_FREE_SPACE_IN_OBJECTS); hr = storage_properties->Add(WPD_STORAGE_FREE_SPACE_IN_OBJECTS);
hr = storage_properties->Add(WPD_STORAGE_ACCESS_CAPABILITY); hr = storage_properties->Add(WPD_STORAGE_ACCESS_CAPABILITY);
hr = storage_properties->Add(WPD_STORAGE_FILE_SYSTEM_TYPE); hr = storage_properties->Add(WPD_STORAGE_FILE_SYSTEM_TYPE);
hr = storage_properties->Add(WPD_STORAGE_TYPE);
hr = storage_properties->Add(WPD_OBJECT_NAME); hr = storage_properties->Add(WPD_OBJECT_NAME);
Py_END_ALLOW_THREADS; Py_END_ALLOW_THREADS;
if (FAILED(hr)) {hresult_set_exc("Failed to create collection of properties for storage query", hr); goto end; } if (FAILED(hr)) {hresult_set_exc("Failed to create collection of properties for storage query", hr); goto end; }
@ -145,6 +146,7 @@ PyObject* get_storage_info(IPortableDevice *device) { // {{{
values->GetUnsignedLargeIntegerValue(WPD_STORAGE_CAPACITY_IN_OBJECTS, &capacity_objects); values->GetUnsignedLargeIntegerValue(WPD_STORAGE_CAPACITY_IN_OBJECTS, &capacity_objects);
values->GetUnsignedLargeIntegerValue(WPD_STORAGE_FREE_SPACE_IN_BYTES, &free_space); values->GetUnsignedLargeIntegerValue(WPD_STORAGE_FREE_SPACE_IN_BYTES, &free_space);
values->GetUnsignedLargeIntegerValue(WPD_STORAGE_FREE_SPACE_IN_OBJECTS, &free_objects); values->GetUnsignedLargeIntegerValue(WPD_STORAGE_FREE_SPACE_IN_OBJECTS, &free_objects);
values->GetUnsignedIntegerValue(WPD_STORAGE_TYPE, &storage_type);
desc = Py_False; desc = Py_False;
if (SUCCEEDED(values->GetUnsignedIntegerValue(WPD_STORAGE_ACCESS_CAPABILITY, &access)) && access == WPD_STORAGE_ACCESS_CAPABILITY_READWRITE) desc = Py_True; if (SUCCEEDED(values->GetUnsignedIntegerValue(WPD_STORAGE_ACCESS_CAPABILITY, &access)) && access == WPD_STORAGE_ACCESS_CAPABILITY_READWRITE) desc = Py_True;
soid = PyUnicode_FromWideChar(object_ids[i], wcslen(object_ids[i])); soid = PyUnicode_FromWideChar(object_ids[i], wcslen(object_ids[i]));
@ -167,6 +169,25 @@ PyObject* get_storage_info(IPortableDevice *device) { // {{{
if (desc != NULL) { PyDict_SetItemString(so, "filesystem", desc); Py_DECREF(desc);} if (desc != NULL) { PyDict_SetItemString(so, "filesystem", desc); Py_DECREF(desc);}
CoTaskMemFree(storage_desc); storage_desc = NULL; CoTaskMemFree(storage_desc); storage_desc = NULL;
} }
switch(storage_type) {
case WPD_STORAGE_TYPE_REMOVABLE_RAM:
st = L"removable_ram";
break;
case WPD_STORAGE_TYPE_REMOVABLE_ROM:
st = L"removable_rom";
break;
case WPD_STORAGE_TYPE_FIXED_RAM:
st = L"fixed_ram";
break;
case WPD_STORAGE_TYPE_FIXED_ROM:
st = L"fixed_rom";
break;
default:
st = L"unknown_unknown";
}
desc = PyUnicode_FromWideChar(st, wcslen(st));
if (desc != NULL) {PyDict_SetItemString(so, "type", desc); Py_DECREF(desc);}
desc = NULL;
PyList_Append(storage, so); PyList_Append(storage, so);
Py_DECREF(so); Py_DECREF(so);
} }

View File

@ -13,7 +13,7 @@ from future_builtins import zip
from itertools import chain from itertools import chain
from calibre import as_unicode, prints from calibre import as_unicode, prints
from calibre.constants import plugins, __appname__, numeric_version from calibre.constants import plugins, __appname__, numeric_version, isxp
from calibre.ptempfile import SpooledTemporaryFile from calibre.ptempfile import SpooledTemporaryFile
from calibre.devices.errors import OpenFailed, DeviceError, BlacklistedDevice from calibre.devices.errors import OpenFailed, DeviceError, BlacklistedDevice
from calibre.devices.mtp.base import MTPDeviceBase, debug from calibre.devices.mtp.base import MTPDeviceBase, debug
@ -52,9 +52,14 @@ class MTP_DEVICE(MTPDeviceBase):
self.start_thread = None self.start_thread = None
self._filesystem_cache = None self._filesystem_cache = None
self.eject_dev_on_next_scan = False self.eject_dev_on_next_scan = False
self.current_device_data = {}
def startup(self): def startup(self):
self.start_thread = threading.current_thread() self.start_thread = threading.current_thread()
if isxp:
self.wpd = None
self.wpd_error = _('MTP devices are not supported on Windows XP')
else:
self.wpd, self.wpd_error = plugins['wpd'] self.wpd, self.wpd_error = plugins['wpd']
if self.wpd is not None: if self.wpd is not None:
try: try:
@ -196,6 +201,12 @@ class MTP_DEVICE(MTPDeviceBase):
if not devdata.get('has_storage', False): return False if not devdata.get('has_storage', False): return False
has_rw_storage = False has_rw_storage = False
for s in devdata.get('storage', []): for s in devdata.get('storage', []):
if s.get('filesystem', None) == 'DCF':
# DCF filesystem indicates a camera or an iPhone
# See https://bugs.launchpad.net/calibre/+bug/1054562
continue
if s.get('type', 'unknown_unknown').split('_')[-1] == 'rom':
continue # Read only storage
if s.get('rw', False): if s.get('rw', False):
has_rw_storage = True has_rw_storage = True
break break
@ -280,6 +291,8 @@ class MTP_DEVICE(MTPDeviceBase):
raise BlacklistedDevice( raise BlacklistedDevice(
'The %s device has been blacklisted by the user'%(connected_device,)) 'The %s device has been blacklisted by the user'%(connected_device,))
storage.sort(key=lambda x:x.get('id', 'zzzzz'))
self._main_id = storage[0]['id'] self._main_id = storage[0]['id']
if len(storage) > 1: if len(storage) > 1:
self._carda_id = storage[1]['id'] self._carda_id = storage[1]['id']
@ -291,6 +304,11 @@ class MTP_DEVICE(MTPDeviceBase):
_('Unknown MTP device')) _('Unknown MTP device'))
self.currently_connected_pnp_id = connected_device self.currently_connected_pnp_id = connected_device
self.current_serial_num = snum self.current_serial_num = snum
self.current_device_data = devdata.copy()
def device_debug_info(self):
import pprint
return pprint.pformat(self.current_device_data)
@same_thread @same_thread
def get_basic_device_information(self): def get_basic_device_information(self):

View File

@ -687,7 +687,7 @@ class PRST1(USBMS):
'WHERE _id = ?') 'WHERE _id = ?')
t = (collectionId,) t = (collectionId,)
cursor.execute(query, t) cursor.execute(query, t)
debug_print('Deleted Collection: ' + collection) debug_print('Deleted Collection: ' + repr(collection))
connection.commit() connection.commit()
cursor.close() cursor.close()

View File

@ -744,22 +744,6 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
except: except:
self._close_device_socket() self._close_device_socket()
return (self.is_connected, self) return (self.is_connected, self)
if getattr(self, 'broadcast_socket', None) is not None:
while True:
ans = select.select((self.broadcast_socket,), (), (), 0)
if len(ans[0]) > 0:
try:
packet = self.broadcast_socket.recvfrom(100)
remote = packet[1]
message = str(self.ZEROCONF_CLIENT_STRING + b' (on ' +
str(socket.gethostname().partition('.')[0]) +
b'),' + str(self.port))
self._debug('received broadcast', packet, message)
self.broadcast_socket.sendto(message, remote)
except:
pass
else:
break
if getattr(self, 'listen_socket', None) is not None: if getattr(self, 'listen_socket', None) is not None:
try: try:
@ -902,10 +886,16 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
return False return False
def get_gui_name(self): def get_gui_name(self):
if self.client_device_kind: if getattr(self, 'client_device_kind', None):
return self.gui_name_template%(self.gui_name, self.client_device_kind) return self.gui_name_template%(self.gui_name, self.client_device_kind)
return self.gui_name return self.gui_name
def config_widget(self):
from calibre.gui2.device_drivers.configwidget import ConfigWidget
cw = ConfigWidget(self.settings(), self.FORMATS, self.SUPPORTS_SUB_DIRS,
self.MUST_READ_METADATA, self.SUPPORTS_USE_AUTHOR_SORT,
self.EXTRA_CUSTOMIZATION_MESSAGE, self)
return cw
@synchronous('sync_lock') @synchronous('sync_lock')
def get_device_information(self, end_session=True): def get_device_information(self, end_session=True):

View File

@ -14,6 +14,8 @@ import os
from calibre.customize.conversion import OutputFormatPlugin, \ from calibre.customize.conversion import OutputFormatPlugin, \
OptionRecommendation OptionRecommendation
from calibre.ptempfile import TemporaryDirectory from calibre.ptempfile import TemporaryDirectory
from calibre.constants import iswindows
from calibre import walk
UNITS = [ UNITS = [
'millimeter', 'millimeter',
@ -148,6 +150,16 @@ class PDFOutput(OutputFormatPlugin):
oeb_output = plugin_for_output_format('oeb') oeb_output = plugin_for_output_format('oeb')
oeb_output.convert(oeb_book, oeb_dir, self.input_plugin, self.opts, self.log) oeb_output.convert(oeb_book, oeb_dir, self.input_plugin, self.opts, self.log)
if iswindows:
# On windows Qt generates an image based PDF if the html uses
# embedded fonts. See https://launchpad.net/bugs/1053906
for f in walk(oeb_dir):
if f.rpartition('.')[-1].lower() in {'ttf', 'otf'}:
self.log.warn('Found embedded font %s, removing it, as '
'embedded fonts on windows are not supported by '
'the PDF Output plugin'%os.path.basename(f))
os.remove(f)
opfpath = glob.glob(os.path.join(oeb_dir, '*.opf'))[0] opfpath = glob.glob(os.path.join(oeb_dir, '*.opf'))[0]
opf = OPF(opfpath, os.path.dirname(opfpath)) opf = OPF(opfpath, os.path.dirname(opfpath))

View File

@ -792,19 +792,16 @@ class OPF(object): # {{{
remove = list(self.authors_path(self.metadata)) remove = list(self.authors_path(self.metadata))
for elem in remove: for elem in remove:
elem.getparent().remove(elem) elem.getparent().remove(elem)
elems = []
for author in val:
attrib = {'{%s}role'%self.NAMESPACES['opf']: 'aut'}
elem = self.create_metadata_element('creator', attrib=attrib)
self.set_text(elem, author.strip())
# Ensure new author element is at the top of the list # Ensure new author element is at the top of the list
# for broken implementations that always use the first # for broken implementations that always use the first
# <dc:creator> element with no attention to the role # <dc:creator> element with no attention to the role
elems.append(elem) for author in reversed(val):
for elem in reversed(elems): elem = self.metadata.makeelement('{%s}creator'%
parent = elem.getparent() self.NAMESPACES['dc'], nsmap=self.NAMESPACES)
parent.remove(elem) elem.tail = '\n'
parent.insert(0, elem) self.metadata.insert(0, elem)
elem.set('{%s}role'%self.NAMESPACES['opf'], 'aut')
self.set_text(elem, author.strip())
return property(fget=fget, fset=fset) return property(fget=fget, fset=fset)
@ -1020,9 +1017,8 @@ class OPF(object): # {{{
def fset(self, val): def fset(self, val):
matches = self.bkp_path(self.metadata) matches = self.bkp_path(self.metadata)
if not matches: if not matches:
attrib = {'{%s}role'%self.NAMESPACES['opf']: 'bkp'} matches = [self.create_metadata_element('contributor')]
matches = [self.create_metadata_element('contributor', matches[0].set('{%s}role'%self.NAMESPACES['opf'], 'bkp')
attrib=attrib)]
self.set_text(matches[0], unicode(val)) self.set_text(matches[0], unicode(val))
return property(fget=fget, fset=fset) return property(fget=fget, fset=fset)
@ -1155,7 +1151,7 @@ class OPF(object): # {{{
def smart_update(self, mi, replace_metadata=False): def smart_update(self, mi, replace_metadata=False):
for attr in ('title', 'authors', 'author_sort', 'title_sort', for attr in ('title', 'authors', 'author_sort', 'title_sort',
'publisher', 'series', 'series_index', 'rating', 'publisher', 'series', 'series_index', 'rating',
'isbn', 'tags', 'category', 'comments', 'isbn', 'tags', 'category', 'comments', 'book_producer',
'pubdate', 'user_categories', 'author_link_map'): 'pubdate', 'user_categories', 'author_link_map'):
val = getattr(mi, attr, None) val = getattr(mi, attr, None)
if val is not None and val != [] and val != (None, None): if val is not None and val != [] and val != (None, None):

View File

@ -10,6 +10,7 @@ __docformat__ = 'restructuredtext en'
import re import re
from collections import namedtuple from collections import namedtuple
from functools import partial from functools import partial
from xml.sax.saxutils import escape
from lxml import etree from lxml import etree
@ -289,6 +290,7 @@ class Chunker(object):
self.chunk_selector = ('S', aid) self.chunk_selector = ('S', aid)
def chunk_up_text(self, text): def chunk_up_text(self, text):
text = escape(text)
text = text.encode('utf-8') text = text.encode('utf-8')
ans = [] ans = []

View File

@ -17,6 +17,7 @@ from calibre.customize.ui import is_disabled
from calibre.devices.bambook.driver import BAMBOOK from calibre.devices.bambook.driver import BAMBOOK
from calibre.gui2.dialogs.smartdevice import SmartdeviceDialog from calibre.gui2.dialogs.smartdevice import SmartdeviceDialog
from calibre.gui2 import info_dialog, question_dialog from calibre.gui2 import info_dialog, question_dialog
from calibre.library.server import server_config as content_server_config
class ShareConnMenu(QMenu): # {{{ class ShareConnMenu(QMenu): # {{{
@ -90,7 +91,12 @@ class ShareConnMenu(QMenu): # {{{
if running: if running:
listen_on = (verify_ipV4_address(tweaks['server_listen_on']) or listen_on = (verify_ipV4_address(tweaks['server_listen_on']) or
get_external_ip()) get_external_ip())
text = _('Stop Content Server') + ' [%s]'%listen_on try :
cs_port = content_server_config().parse().port
ip_text = _(' [%s, port %d]')%(listen_on, cs_port)
except:
ip_text = ' [%s]'%listen_on
text = _('Stop Content Server') + ip_text
self.toggle_server_action.setText(text) self.toggle_server_action.setText(text)
def hide_smartdevice_menus(self): def hide_smartdevice_menus(self):

View File

@ -12,7 +12,8 @@ import weakref
from PyQt4.Qt import (QWidget, QListWidgetItem, Qt, QToolButton, QLabel, from PyQt4.Qt import (QWidget, QListWidgetItem, Qt, QToolButton, QLabel,
QTabWidget, QGridLayout, QListWidget, QIcon, QLineEdit, QVBoxLayout, QTabWidget, QGridLayout, QListWidget, QIcon, QLineEdit, QVBoxLayout,
QPushButton, QGroupBox, QScrollArea, QHBoxLayout, QComboBox, QPushButton, QGroupBox, QScrollArea, QHBoxLayout, QComboBox,
pyqtSignal, QSizePolicy, QDialog, QDialogButtonBox) pyqtSignal, QSizePolicy, QDialog, QDialogButtonBox, QPlainTextEdit,
QApplication)
from calibre.ebooks import BOOK_EXTENSIONS from calibre.ebooks import BOOK_EXTENSIONS
from calibre.gui2 import error_dialog from calibre.gui2 import error_dialog
@ -372,15 +373,19 @@ class MTPConfig(QTabWidget):
_('&Ignore the %s in calibre')%device.current_friendly_name, _('&Ignore the %s in calibre')%device.current_friendly_name,
self.base) self.base)
b.clicked.connect(self.ignore_device) b.clicked.connect(self.ignore_device)
self.show_debug_button = bd = QPushButton(QIcon(I('debug.png')),
_('Show device information'))
bd.clicked.connect(self.show_debug_info)
l.addWidget(b, 0, 0, 1, 2) l.addWidget(b, 0, 0, 1, 2)
l.addWidget(la, 1, 0, 1, 1) l.addWidget(la, 1, 0, 1, 1)
l.addWidget(self.formats, 2, 0, 3, 1) l.addWidget(self.formats, 2, 0, 4, 1)
l.addWidget(self.send_to, 2, 1, 1, 1) l.addWidget(self.send_to, 2, 1, 1, 1)
l.addWidget(self.template, 3, 1, 1, 1) l.addWidget(self.template, 3, 1, 1, 1)
l.setRowStretch(4, 10) l.addWidget(self.show_debug_button, 4, 1, 1, 1)
l.addWidget(r, 5, 0, 1, 2) l.setRowStretch(5, 10)
l.setRowStretch(5, 100) l.addWidget(r, 6, 0, 1, 2)
l.setRowStretch(6, 100)
self.igntab = IgnoredDevices(self.device.prefs['history'], self.igntab = IgnoredDevices(self.device.prefs['history'],
self.device.prefs['blacklist']) self.device.prefs['blacklist'])
@ -388,6 +393,26 @@ class MTPConfig(QTabWidget):
self.setCurrentIndex(1 if msg else 0) self.setCurrentIndex(1 if msg else 0)
def show_debug_info(self):
info = self.device.device_debug_info()
d = QDialog(self)
d.l = l = QVBoxLayout()
d.setLayout(l)
d.v = v = QPlainTextEdit()
d.setWindowTitle(self.device.get_gui_name())
v.setPlainText(info)
v.setMinimumWidth(400)
v.setMinimumHeight(350)
l.addWidget(v)
bb = d.bb = QDialogButtonBox(QDialogButtonBox.Close)
bb.accepted.connect(d.accept)
bb.rejected.connect(d.reject)
l.addWidget(bb)
bb.addButton(_('Copy to clipboard'), bb.ActionRole)
bb.clicked.connect(lambda :
QApplication.clipboard().setText(v.toPlainText()))
d.exec_()
def ignore_device(self): def ignore_device(self):
self.igntab.ignore_device(self.device.current_serial_num) self.igntab.ignore_device(self.device.current_serial_num)
self.base.b.setEnabled(False) self.base.b.setEnabled(False)

View File

@ -10,7 +10,7 @@ import copy
from PyQt4.Qt import Qt, QComboBox, QListWidgetItem from PyQt4.Qt import Qt, QComboBox, QListWidgetItem
from calibre.customize.ui import is_disabled from calibre.customize.ui import is_disabled
from calibre.gui2 import error_dialog, question_dialog from calibre.gui2 import error_dialog, question_dialog, warning_dialog
from calibre.gui2.device import device_name_for_plugboards from calibre.gui2.device import device_name_for_plugboards
from calibre.gui2.dialogs.template_line_editor import TemplateLineEditor from calibre.gui2.dialogs.template_line_editor import TemplateLineEditor
from calibre.gui2.preferences import ConfigWidgetBase, test_widget from calibre.gui2.preferences import ConfigWidgetBase, test_widget
@ -254,6 +254,15 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
show=True) show=True)
self.new_device.setCurrentIndex(0) self.new_device.setCurrentIndex(0)
return return
if self.current_format == plugboard_any_format_value and \
self.current_device == plugboard_content_server_value:
warning_dialog(self, '',
_('The {0} device supports only the {1} format(s).').
format(plugboard_content_server_value,
', '.join(plugboard_content_server_formats)),
show=True)
self.set_fields() self.set_fields()
def new_format_changed(self, txt): def new_format_changed(self, txt):

View File

@ -97,7 +97,7 @@ class EbookscomStore(BasicStoreConfig, StorePlugin):
with closing(br.open(url + id, timeout=timeout)) as nf: with closing(br.open(url + id, timeout=timeout)) as nf:
pdoc = html.fromstring(nf.read()) pdoc = html.fromstring(nf.read())
price_l = pdoc.xpath('//span[@class="price"]/text()') price_l = pdoc.xpath('//div[@class="book-info"]/div[@class="price"]/text()')
if price_l: if price_l:
price = price_l[0] price = price_l[0]
search_result.price = price.strip() search_result.price = price.strip()

View File

@ -15,7 +15,8 @@ from binascii import hexlify, unhexlify
import cherrypy import cherrypy
from calibre.utils.date import isoformat from calibre.utils.date import isoformat
from calibre.utils.config import prefs from calibre.utils.config import prefs, tweaks
from calibre.ebooks.metadata import title_sort
from calibre.ebooks.metadata.book.json_codec import JsonCodec from calibre.ebooks.metadata.book.json_codec import JsonCodec
from calibre.utils.icu import sort_key from calibre.utils.icu import sort_key
from calibre.library.server import custom_fields_to_display from calibre.library.server import custom_fields_to_display
@ -118,12 +119,16 @@ class AjaxServer(object):
# Get book metadata {{{ # Get book metadata {{{
def ajax_book_to_json(self, book_id, get_category_urls=True): def ajax_book_to_json(self, book_id, get_category_urls=True,
device_compatible=False):
mi = self.db.get_metadata(book_id, index_is_id=True) mi = self.db.get_metadata(book_id, index_is_id=True)
if not device_compatible:
try: try:
mi.rating = mi.rating/2. mi.rating = mi.rating/2.
except: except:
mi.rating = 0.0 mi.rating = 0.0
data = self.ajax_json_codec.encode_book_metadata(mi) data = self.ajax_json_codec.encode_book_metadata(mi)
for x in ('publication_type', 'size', 'db_id', 'lpath', 'mime', for x in ('publication_type', 'size', 'db_id', 'lpath', 'mime',
'rights', 'book_producer'): 'rights', 'book_producer'):
@ -131,6 +136,8 @@ class AjaxServer(object):
data['cover'] = absurl(self.opts.url_prefix, u'/get/cover/%d'%book_id) data['cover'] = absurl(self.opts.url_prefix, u'/get/cover/%d'%book_id)
data['thumbnail'] = absurl(self.opts.url_prefix, u'/get/thumb/%d'%book_id) data['thumbnail'] = absurl(self.opts.url_prefix, u'/get/thumb/%d'%book_id)
if not device_compatible:
mi.format_metadata = {k.lower():dict(v) for k, v in mi.format_metadata = {k.lower():dict(v) for k, v in
mi.format_metadata.iteritems()} mi.format_metadata.iteritems()}
for v in mi.format_metadata.itervalues(): for v in mi.format_metadata.itervalues():
@ -177,11 +184,20 @@ class AjaxServer(object):
unicode(tag.id)) unicode(tag.id))
break break
category_urls[key] = dbtags category_urls[key] = dbtags
else:
series = data.get('series', None)
if series:
tsorder = tweaks['save_template_title_series_sorting']
series = title_sort(series, order=tsorder)
else:
series = ''
data['_series_sort_'] = series
return data, mi.last_modified return data, mi.last_modified
@Endpoint(set_last_modified=False) @Endpoint(set_last_modified=False)
def ajax_book(self, book_id, category_urls='true', id_is_uuid='false'): def ajax_book(self, book_id, category_urls='true', id_is_uuid='false',
device_compatible='false'):
''' '''
Return the metadata of the book as a JSON dictionary. Return the metadata of the book as a JSON dictionary.
@ -197,7 +213,8 @@ class AjaxServer(object):
else: else:
book_id = int(book_id) book_id = int(book_id)
data, last_modified = self.ajax_book_to_json(book_id, data, last_modified = self.ajax_book_to_json(book_id,
get_category_urls=category_urls.lower()=='true') get_category_urls=category_urls.lower()=='true',
device_compatible=device_compatible.lower()=='true');
except: except:
raise cherrypy.HTTPError(404, 'No book with id: %r'%book_id) raise cherrypy.HTTPError(404, 'No book with id: %r'%book_id)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,9 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: calibre 0.8.70\n" "Project-Id-Version: calibre 0.9.0\n"
"POT-Creation-Date: 2012-09-21 13:10+IST\n" "POT-Creation-Date: 2012-09-28 10:04+IST\n"
"PO-Revision-Date: 2012-09-21 13:10+IST\n" "PO-Revision-Date: 2012-09-28 10:04+IST\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"
@ -33,8 +33,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/kobo/books.py:27 #: /home/kovid/work/calibre/src/calibre/devices/kobo/books.py:27
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:656 #: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:656
#: /home/kovid/work/calibre/src/calibre/devices/mtp/books.py:44 #: /home/kovid/work/calibre/src/calibre/devices/mtp/books.py:44
#: /home/kovid/work/calibre/src/calibre/devices/mtp/unix/driver.py:209 #: /home/kovid/work/calibre/src/calibre/devices/mtp/unix/driver.py:223
#: /home/kovid/work/calibre/src/calibre/devices/mtp/windows/driver.py:218 #: /home/kovid/work/calibre/src/calibre/devices/mtp/windows/driver.py:229
#: /home/kovid/work/calibre/src/calibre/devices/nook/driver.py:70 #: /home/kovid/work/calibre/src/calibre/devices/nook/driver.py:70
#: /home/kovid/work/calibre/src/calibre/devices/nook/driver.py:71 #: /home/kovid/work/calibre/src/calibre/devices/nook/driver.py:71
#: /home/kovid/work/calibre/src/calibre/devices/prs505/sony_cache.py:661 #: /home/kovid/work/calibre/src/calibre/devices/prs505/sony_cache.py:661
@ -79,8 +79,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/mobi.py:472 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/mobi.py:472
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/mobi.py:474 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/mobi.py:474
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/mobi.py:476 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/mobi.py:476
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/opf2.py:1188 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/opf2.py:1184
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/opf2.py:1299 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/opf2.py:1295
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/pdb.py:44 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/pdb.py:44
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/pdf.py:88 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/pdf.py:88
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/plucker.py:25 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/plucker.py:25
@ -204,7 +204,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/customize/__init__.py:156 #: /home/kovid/work/calibre/src/calibre/customize/__init__.py:156
#: /home/kovid/work/calibre/src/calibre/gui2/actions/preferences.py:54 #: /home/kovid/work/calibre/src/calibre/gui2/actions/preferences.py:54
#: /home/kovid/work/calibre/src/calibre/gui2/actions/preferences.py:59 #: /home/kovid/work/calibre/src/calibre/gui2/actions/preferences.py:59
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:356 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:357
msgid "Cannot configure" msgid "Cannot configure"
msgstr "" msgstr ""
@ -586,7 +586,7 @@ msgid "Control how calibre downloads ebook metadata from the net"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1125 #: /home/kovid/work/calibre/src/calibre/customize/builtins.py:1125
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:387 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:392
msgid "Ignored devices" msgid "Ignored devices"
msgstr "" msgstr ""
@ -1109,8 +1109,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/bambook/driver.py:268 #: /home/kovid/work/calibre/src/calibre/devices/bambook/driver.py:268
#: /home/kovid/work/calibre/src/calibre/devices/bambook/driver.py:324 #: /home/kovid/work/calibre/src/calibre/devices/bambook/driver.py:324
#: /home/kovid/work/calibre/src/calibre/devices/mtp/driver.py:361 #: /home/kovid/work/calibre/src/calibre/devices/mtp/driver.py:361
#: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1088 #: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1078
#: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1090 #: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1080
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:277 #: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:277
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:279 #: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:279
msgid "Transferring books to device..." msgid "Transferring books to device..."
@ -1121,8 +1121,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:480 #: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:480
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:515 #: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:515
#: /home/kovid/work/calibre/src/calibre/devices/mtp/driver.py:398 #: /home/kovid/work/calibre/src/calibre/devices/mtp/driver.py:398
#: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1101 #: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1091
#: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1112 #: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1102
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:301 #: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:301
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:332 #: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:332
msgid "Adding books to device metadata listing..." msgid "Adding books to device metadata listing..."
@ -1144,8 +1144,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/bambook/driver.py:374 #: /home/kovid/work/calibre/src/calibre/devices/bambook/driver.py:374
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:468 #: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:468
#: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:475 #: /home/kovid/work/calibre/src/calibre/devices/kobo/driver.py:475
#: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1140 #: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1130
#: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1146 #: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1136
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:366 #: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:366
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:371 #: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:371
msgid "Removing books from device metadata listing..." msgid "Removing books from device metadata listing..."
@ -1578,7 +1578,7 @@ msgid "Communicate with MTP devices"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/mtp/driver.py:141 #: /home/kovid/work/calibre/src/calibre/devices/mtp/driver.py:141
#: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:913 #: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:903
#: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:95 #: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:95
msgid "Get device information..." msgid "Get device information..."
msgstr "" msgstr ""
@ -1644,12 +1644,16 @@ msgstr ""
msgid "All books removed" msgid "All books removed"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/mtp/unix/driver.py:194 #: /home/kovid/work/calibre/src/calibre/devices/mtp/unix/driver.py:195
#: /home/kovid/work/calibre/src/calibre/devices/mtp/windows/driver.py:291 #: /home/kovid/work/calibre/src/calibre/devices/mtp/windows/driver.py:304
msgid "Unknown MTP device" msgid "Unknown MTP device"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/mtp/windows/driver.py:64 #: /home/kovid/work/calibre/src/calibre/devices/mtp/windows/driver.py:61
msgid "MTP devices are not supported on Windows XP"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/mtp/windows/driver.py:69
msgid "The Windows Portable Devices service is not available on your computer. You may need to install Windows Media Player 11 or newer and/or restart your computer" msgid "The Windows Portable Devices service is not available on your computer. You may need to install Windows Media Player 11 or newer and/or restart your computer"
msgstr "" msgstr ""
@ -1850,22 +1854,22 @@ msgstr ""
msgid "Use this option if you want to force the driver to listen on a particular IP address. The driver will listen only on the entered address, and this address will be the one advertized over mDNS (bonjour)." msgid "Use this option if you want to force the driver to listen on a particular IP address. The driver will listen only on the entered address, and this address will be the one advertized over mDNS (bonjour)."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:775 #: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:759
#, python-format #, python-format
msgid "Too many connection attempts from %s" msgid "Too many connection attempts from %s"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1250 #: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1240
#, python-format #, python-format
msgid "Invalid port in options: %s" msgid "Invalid port in options: %s"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1258 #: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1248
#, python-format #, python-format
msgid "Failed to connect to port %d. Try a different value." msgid "Failed to connect to port %d. Try a different value."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1270 #: /home/kovid/work/calibre/src/calibre/devices/smart_device_app/driver.py:1260
msgid "Failed to allocate a random port" msgid "Failed to allocate a random port"
msgstr "" msgstr ""
@ -2491,47 +2495,47 @@ msgstr ""
msgid "Use the new PDF conversion engine." msgid "Use the new PDF conversion engine."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:70 #: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:72
#, python-format #, python-format
msgid "The unit of measure. Default is inch. Choices are %s Note: This does not override the unit for margins!" msgid "The unit of measure. Default is inch. Choices are %s Note: This does not override the unit for margins!"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:75 #: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:77
#, python-format #, python-format
msgid "The size of the paper. This size will be overridden when a non default output profile is used. Default is letter. Choices are %s" msgid "The size of the paper. This size will be overridden when a non default output profile is used. Default is letter. Choices are %s"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:79 #: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:81
msgid "Custom size of the document. Use the form widthxheight EG. `123x321` to specify the width and height. This overrides any specified paper-size." msgid "Custom size of the document. Use the form widthxheight EG. `123x321` to specify the width and height. This overrides any specified paper-size."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:84 #: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:86
#, python-format #, python-format
msgid "The orientation of the page. Default is portrait. Choices are %s" msgid "The orientation of the page. Default is portrait. Choices are %s"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:88 #: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:90
msgid "Preserve the aspect ratio of the cover, instead of stretching it to fill the full first page of the generated pdf." msgid "Preserve the aspect ratio of the cover, instead of stretching it to fill the full first page of the generated pdf."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:93 #: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:95
msgid "The font family used to render serif fonts" msgid "The font family used to render serif fonts"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:96 #: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:98
msgid "The font family used to render sans-serif fonts" msgid "The font family used to render sans-serif fonts"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:99 #: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:101
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:103 #: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:105
msgid "The font family used to render monospaced fonts" msgid "The font family used to render monospaced fonts"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:106 #: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:108
msgid "The default font size" msgid "The default font size"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:109 #: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plugins/pdf_output.py:111
msgid "The default font size for monospaced text" msgid "The default font size for monospaced text"
msgstr "" msgstr ""
@ -3485,7 +3489,7 @@ msgid ""
"Fetch a cover image/social metadata for the book identified by ISBN from LibraryThing.com\n" "Fetch a cover image/social metadata for the book identified by ISBN from LibraryThing.com\n"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/opf2.py:1491 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/opf2.py:1487
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1279 #: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1279
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:958 #: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:958
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/models.py:41 #: /home/kovid/work/calibre/src/calibre/gui2/store/search/models.py:41
@ -4647,87 +4651,92 @@ msgstr ""
msgid "The selected books will be <b>permanently deleted</b> from your device. Are you sure?" msgid "The selected books will be <b>permanently deleted</b> from your device. Are you sure?"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:32 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:33
msgid "Start wireless device connection" msgid "Start wireless device connection"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:33 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:34
msgid "Stop wireless device connection" msgid "Stop wireless device connection"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:37 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:38
msgid "Connect to folder" msgid "Connect to folder"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:42 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:43
msgid "Connect to iTunes" msgid "Connect to iTunes"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:48 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:49
msgid "Connect to Bambook" msgid "Connect to Bambook"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:62 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:63
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:89 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:90
msgid "Start Content Server" msgid "Start Content Server"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:84 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:85
msgid "Start/stop content server" msgid "Start/stop content server"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:93 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:96
#, python-format
msgid " [%s, port %d]"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:99
msgid "Stop Content Server" msgid "Stop Content Server"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:107 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:113
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:126 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:132
msgid "Email to" msgid "Email to"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:111 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:117
msgid "Email to and delete from library" msgid "Email to and delete from library"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:120 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:126
msgid "(delete from library)" msgid "(delete from library)"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:135 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:141
msgid "Setup email based sharing of books" msgid "Setup email based sharing of books"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:153 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:159
msgid "D" msgid "D"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:153 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:159
msgid "Send to device" msgid "Send to device"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:171 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:177
msgid "Connect/share" msgid "Connect/share"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:209 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:215
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:85 #: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:85
msgid "Stopping" msgid "Stopping"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:210 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:216
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:86 #: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:86
msgid "Stopping server, this could take upto a minute, please wait..." msgid "Stopping server, this could take upto a minute, please wait..."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:229 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:235
msgid "Disable autostart" msgid "Disable autostart"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:230 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:236
msgid "Do you want wireless device connections to be started automatically when calibre starts?" msgid "Do you want wireless device connections to be started automatically when calibre starts?"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:253 #: /home/kovid/work/calibre/src/calibre/gui2/actions/device.py:259
msgid "Many IP addresses. See Start/Stop dialog." msgid "Many IP addresses. See Start/Stop dialog."
msgstr "" msgstr ""
@ -7854,7 +7863,7 @@ msgid "Cannot configure the device while there are running device jobs."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device.py:920 #: /home/kovid/work/calibre/src/calibre/gui2/device.py:920
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:359 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:360
#, python-format #, python-format
msgid "Configure %s" msgid "Configure %s"
msgstr "" msgstr ""
@ -7964,7 +7973,7 @@ msgid "You have enabled the <b>{0}</b> formats for your {1}. The {1} may not sup
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget.py:155 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget.py:155
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:112 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:113
#: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:456 #: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:456
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/plugboard.py:279 #: /home/kovid/work/calibre/src/calibre/gui2/preferences/plugboard.py:279
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/save_template.py:70 #: /home/kovid/work/calibre/src/calibre/gui2/preferences/save_template.py:70
@ -7972,7 +7981,7 @@ msgid "Invalid template"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget.py:156 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget.py:156
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:113 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:114
#: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:457 #: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:457
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/plugboard.py:280 #: /home/kovid/work/calibre/src/calibre/gui2/preferences/plugboard.py:280
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/save_template.py:71 #: /home/kovid/work/calibre/src/calibre/gui2/preferences/save_template.py:71
@ -8000,100 +8009,112 @@ msgstr ""
msgid "Save &template:" msgid "Save &template:"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:56 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:57
msgid "No formats selected" msgid "No formats selected"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:57 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:58
msgid "You must choose at least one format to send to the device" msgid "You must choose at least one format to send to the device"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:85 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:86
msgid "" msgid ""
"<b>Save &template</b> to control the filename and\n" "<b>Save &template</b> to control the filename and\n"
" location of files sent to the device:" " location of files sent to the device:"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:91 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:92
msgid "&Template editor" msgid "&Template editor"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:101 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:102
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/template_line_editor.py:41 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/template_line_editor.py:41
#: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:443 #: /home/kovid/work/calibre/src/calibre/gui2/library/delegates.py:443
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/save_template.py:48 #: /home/kovid/work/calibre/src/calibre/gui2/preferences/save_template.py:48
msgid "Edit template" msgid "Edit template"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:128 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:129
msgid "" msgid ""
"A <b>list of &folders</b> on the device to\n" "A <b>list of &folders</b> on the device to\n"
" which to send ebooks. The first one that exists will be used:" " which to send ebooks. The first one that exists will be used:"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:138 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:139
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:225 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:226
msgid "Browse for a folder on the device" msgid "Browse for a folder on the device"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:166 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:167
msgid "" msgid ""
"Select the devices to be <b>ignored</b>. calibre <b>will not</b>\n" "Select the devices to be <b>ignored</b>. calibre <b>will not</b>\n"
" connect to devices with a checkmark next to their names." " connect to devices with a checkmark next to their names."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:211 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:212
#, python-format #, python-format
msgid "Send the %s format to the folder:" msgid "Send the %s format to the folder:"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:219 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:220
msgid "Folder on the device" msgid "Folder on the device"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:227 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:228
msgid "&Remove rule" msgid "&Remove rule"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:272 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:273
msgid "Format specific sending" msgid "Format specific sending"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:277 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:278
msgid "" msgid ""
"You can create rules that control where ebooks of a specific\n" "You can create rules that control where ebooks of a specific\n"
" format are sent to on the device. These will take precedence over\n" " format are sent to on the device. These will take precedence over\n"
" the folders specified above." " the folders specified above."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:299 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:300
msgid "Add a &new rule" msgid "Add a &new rule"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:337 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:338
#, python-format #, python-format
msgid "The <b>%s</b> device has no serial number, it cannot be configured" msgid "The <b>%s</b> device has no serial number, it cannot be configured"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:342 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:343
msgid "<b>No MTP device connected.</b><p> You can only configure the MTP device plugin when a device is connected." msgid "<b>No MTP device connected.</b><p> You can only configure the MTP device plugin when a device is connected."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:349 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:350
msgid "If you want to un-ignore a previously ignored MTP device, use the \"Ignored devices\" tab." msgid "If you want to un-ignore a previously ignored MTP device, use the \"Ignored devices\" tab."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:369 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:370
#, python-format #, python-format
msgid "Choose the formats to send to the %s" msgid "Choose the formats to send to the %s"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:372 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:373
#, python-format #, python-format
msgid "&Ignore the %s in calibre" msgid "&Ignore the %s in calibre"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:394 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:377
msgid "Show device information"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:411
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/message_box.py:141
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single_download.py:880
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks.py:344
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main_ui.py:220
msgid "Copy to clipboard"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/mtp_config.py:419
#, python-format #, python-format
msgid "The %s will be ignored in calibre" msgid "The %s will be ignored in calibre"
msgstr "" msgstr ""
@ -8818,13 +8839,6 @@ msgstr ""
msgid "Copied" msgid "Copied"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/message_box.py:141
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single_download.py:880
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks.py:344
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main_ui.py:220
msgid "Copy to clipboard"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/message_box.py:196 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/message_box.py:196
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/message_box.py:251 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/message_box.py:251
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single_download.py:944 #: /home/kovid/work/calibre/src/calibre/gui2/metadata/single_download.py:944
@ -17466,13 +17480,13 @@ msgstr ""
msgid "Prefix to prepend to all URLs. Useful for reverseproxying to this server from Apache/nginx/etc." msgid "Prefix to prepend to all URLs. Useful for reverseproxying to this server from Apache/nginx/etc."
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/server/ajax.py:300 #: /home/kovid/work/calibre/src/calibre/library/server/ajax.py:317
#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:342 #: /home/kovid/work/calibre/src/calibre/library/server/browse.py:342
#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:626 #: /home/kovid/work/calibre/src/calibre/library/server/browse.py:626
msgid "All books" msgid "All books"
msgstr "" msgstr ""
#: /home/kovid/work/calibre/src/calibre/library/server/ajax.py:301 #: /home/kovid/work/calibre/src/calibre/library/server/ajax.py:318
#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:341 #: /home/kovid/work/calibre/src/calibre/library/server/browse.py:341
#: /home/kovid/work/calibre/src/calibre/library/server/browse.py:625 #: /home/kovid/work/calibre/src/calibre/library/server/browse.py:625
#: /home/kovid/work/calibre/src/calibre/library/server/opds.py:584 #: /home/kovid/work/calibre/src/calibre/library/server/opds.py:584

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More