mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
sync to trunk.
This commit is contained in:
commit
ec0cc79af3
@ -5,7 +5,7 @@
|
|||||||
# Also, each release can have new and improved recipes.
|
# Also, each release can have new and improved recipes.
|
||||||
|
|
||||||
# - version: ?.?.?
|
# - version: ?.?.?
|
||||||
# date: 2011-??-??
|
# date: 2012-??-??
|
||||||
#
|
#
|
||||||
# new features:
|
# new features:
|
||||||
# - title:
|
# - title:
|
||||||
@ -19,8 +19,68 @@
|
|||||||
# new recipes:
|
# new recipes:
|
||||||
# - title:
|
# - title:
|
||||||
|
|
||||||
|
- version: 0.8.36
|
||||||
|
date: 2012-01-20
|
||||||
|
|
||||||
|
new features:
|
||||||
|
- title: "Decrease startup time for large libraries with at least one composite custom column by reading format info on demand"
|
||||||
|
|
||||||
|
- title: "When automatically deleting news older than x days, from the calibre library, only delete the book if it both has the tag News and the author calibre. This prevents accidental deletion of books tagged with News by the user."
|
||||||
|
|
||||||
|
- title: "Driver for Infibeam Pi 2"
|
||||||
|
|
||||||
|
- title: "Add a Tag Editor for tags like custom columns to the edit metadata dialog"
|
||||||
|
|
||||||
|
bug fixes:
|
||||||
|
- title: "E-book viewer: Fix regression in 0.8.35 that caused viewer to raise an error on books that did not define a language"
|
||||||
|
|
||||||
|
- title: "Content server: Fix grouping for categories based on custom columns."
|
||||||
|
tickets: [919011]
|
||||||
|
|
||||||
|
- title: "Edit metadata dialog: When setting the series from a format or via metadata download, ensure that the series index is not automatically changed, when closing the dialog."
|
||||||
|
tickets: [918751]
|
||||||
|
|
||||||
|
- title: "When reading metadata from Topaz (azw1) files, handle non ascii metadata correctly."
|
||||||
|
tickets: [917419]
|
||||||
|
|
||||||
|
- title: "CHM Input: Do not choke on CHM files with non ascii internal filenames on windows."
|
||||||
|
tickets: [917696]
|
||||||
|
|
||||||
|
- title: "Fix reading metadata from CHM files with non-ascii titles"
|
||||||
|
|
||||||
|
- title: "Fix HTML 5 parser choking on comments"
|
||||||
|
|
||||||
|
- title: "If calibre is started from a directory that does not exist, automatically use the home directory as the working directory, instead of crashing"
|
||||||
|
|
||||||
|
- title: "Fix iriver story HD Wi-Fi device and external SD card swapped"
|
||||||
|
tickets: [916364]
|
||||||
|
|
||||||
|
- title: "Content server: Fix ugly URLs for specific format download in the book details and permalink panels"
|
||||||
|
|
||||||
|
- title: "When adding FB2 files do not set the date field from the metadata in the file"
|
||||||
|
|
||||||
|
improved recipes:
|
||||||
|
- OReilly Premuim
|
||||||
|
- Variety
|
||||||
|
- Blic
|
||||||
|
- New Journal of Physics
|
||||||
|
- Der Tagesspiegel
|
||||||
|
|
||||||
|
new recipes:
|
||||||
|
- title: Tweakers.net
|
||||||
|
author: Roedi06
|
||||||
|
|
||||||
|
- title: Village Voice
|
||||||
|
author: Barty
|
||||||
|
|
||||||
|
- title: Edge.org Conversations
|
||||||
|
author: levien
|
||||||
|
|
||||||
|
- title: Novi list - printed edition
|
||||||
|
author: Darko Miletic
|
||||||
|
|
||||||
- version: 0.8.35
|
- version: 0.8.35
|
||||||
date: 2011-01-13
|
date: 2012-01-13
|
||||||
|
|
||||||
new features:
|
new features:
|
||||||
- title: "Metadata plugboards: Allow creation of plugboards for email delivery."
|
- title: "Metadata plugboards: Allow creation of plugboards for email delivery."
|
||||||
|
50
recipes/al_masry_al_youm.recipe
Normal file
50
recipes/al_masry_al_youm.recipe
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2011, Pat Stapleton <pat.stapleton at gmail.com>'
|
||||||
|
'''
|
||||||
|
abc.net.au/news
|
||||||
|
'''
|
||||||
|
import re
|
||||||
|
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||||
|
|
||||||
|
class TheDailyNewsEG(BasicNewsRecipe):
|
||||||
|
title = u'al-masry al-youm'
|
||||||
|
__author__ = 'Omm Mishmishah'
|
||||||
|
description = 'Independent News from Egypt'
|
||||||
|
masthead_url = 'http://www.almasryalyoum.com/sites/default/files/img/english_logo.png'
|
||||||
|
cover_url = 'http://www.almasryalyoum.com/sites/default/files/img/english_logo.png'
|
||||||
|
|
||||||
|
auto_cleanup = True
|
||||||
|
oldest_article = 7
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
no_stylesheets = False
|
||||||
|
#delay = 1
|
||||||
|
use_embedded_content = False
|
||||||
|
encoding = 'utf8'
|
||||||
|
publisher = 'Independent News Egypt'
|
||||||
|
category = 'News, Egypt, World'
|
||||||
|
language = 'en_EG'
|
||||||
|
publication_type = 'newsportal'
|
||||||
|
# preprocess_regexps = [(re.compile(r'<!--.*?-->', re.DOTALL), lambda m: '')]
|
||||||
|
#Remove annoying map links (inline-caption class is also used for some image captions! hence regex to match maps.google)
|
||||||
|
preprocess_regexps = [(re.compile(r'<a class="inline-caption" href="http://maps\.google\.com.*?/a>', re.DOTALL), lambda m: '')]
|
||||||
|
conversion_options = {
|
||||||
|
'comments' : description
|
||||||
|
,'tags' : category
|
||||||
|
,'language' : language
|
||||||
|
,'publisher' : publisher
|
||||||
|
,'linearize_tables': False
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_only_tags = [dict(attrs={'class':['article section']})]
|
||||||
|
|
||||||
|
remove_tags = [dict(attrs={'class':['related', 'tags', 'tools', 'attached-content ready',
|
||||||
|
'inline-content story left', 'inline-content map left contracted', 'published',
|
||||||
|
'story-map', 'statepromo', 'topics', ]})]
|
||||||
|
|
||||||
|
remove_attributes = ['width','height']
|
||||||
|
|
||||||
|
feeds = [(u'English News', u'http://www.almasryalyoum.com/en/rss_feed_term/113/rss.xml'),
|
||||||
|
(u'News Features', u'http://www.almasryalyoum.com/en/rss_feed_term/115/rss.xml'),
|
||||||
|
(u'Culture', u'http://www.almasryalyoum.com/en/rss_feed_term/133/rss.xml'),
|
||||||
|
(u'Cinema', u'http://www.almasryalyoum.com/en/rss_feed_term/134/rss.xml')
|
||||||
|
]
|
72
recipes/klip_me.recipe
Normal file
72
recipes/klip_me.recipe
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class AdvancedUserRecipe1299694372(BasicNewsRecipe):
|
||||||
|
title = u'Klipme'
|
||||||
|
__author__ = 'Ken Sun'
|
||||||
|
publisher = 'Klip.me'
|
||||||
|
category = 'info, custom, Klip.me'
|
||||||
|
oldest_article = 365
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
no_stylesheets = True
|
||||||
|
remove_javascript = True
|
||||||
|
remove_tags = [
|
||||||
|
dict(name='div', attrs={'id':'text_controls_toggle'})
|
||||||
|
,dict(name='script')
|
||||||
|
,dict(name='div', attrs={'id':'text_controls'})
|
||||||
|
,dict(name='div', attrs={'id':'editing_controls'})
|
||||||
|
,dict(name='div', attrs={'class':'bar bottom'})
|
||||||
|
]
|
||||||
|
use_embedded_content = False
|
||||||
|
needs_subscription = True
|
||||||
|
INDEX = u'http://www.klip.me'
|
||||||
|
LOGIN = INDEX + u'/fav/signin?callback=/fav'
|
||||||
|
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
(u'Klip.me unread', u'http://www.klip.me/fav'),
|
||||||
|
(u'Klip.me started', u'http://www.klip.me/fav?s=starred')
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_browser(self):
|
||||||
|
br = BasicNewsRecipe.get_browser()
|
||||||
|
if self.username is not None:
|
||||||
|
br.open(self.LOGIN)
|
||||||
|
br.select_form(nr=0)
|
||||||
|
br['Email'] = self.username
|
||||||
|
if self.password is not None:
|
||||||
|
br['Passwd'] = self.password
|
||||||
|
br.submit()
|
||||||
|
return br
|
||||||
|
|
||||||
|
def parse_index(self):
|
||||||
|
totalfeeds = []
|
||||||
|
lfeeds = self.get_feeds()
|
||||||
|
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)
|
||||||
|
for item in soup.findAll('table',attrs={'class':['item','item new']}):
|
||||||
|
atag = item.a
|
||||||
|
if atag and atag.has_key('href'):
|
||||||
|
url = atag['href']
|
||||||
|
articles.append({
|
||||||
|
'url' :url
|
||||||
|
})
|
||||||
|
totalfeeds.append((feedtitle, articles))
|
||||||
|
return totalfeeds
|
||||||
|
|
||||||
|
def print_version(self, url):
|
||||||
|
return 'http://www.klip.me' + url
|
||||||
|
|
||||||
|
def populate_article_metadata(self, article, soup, first):
|
||||||
|
article.title = soup.find('title').contents[0].strip()
|
||||||
|
|
||||||
|
def postprocess_html(self, soup, first_fetch):
|
||||||
|
for link_tag in soup.findAll(attrs={"id" : "story"}):
|
||||||
|
link_tag.insert(0,'<h1>'+soup.find('title').contents[0].strip()+'</h1>')
|
||||||
|
print link_tag
|
||||||
|
|
||||||
|
return soup
|
||||||
|
|
@ -1,16 +1,35 @@
|
|||||||
__license__ = 'GPL v3'
|
##
|
||||||
__copyright__ = '2008-2010, AprilHare, Darko Miletic <darko.miletic at gmail.com>'
|
## Title: Microwave Journal RSS recipe
|
||||||
|
## Contact: AprilHare, Darko Miletic <darko.miletic at gmail.com>
|
||||||
|
##
|
||||||
|
## License: GNU General Public License v3 - http://www.gnu.org/copyleft/gpl.html
|
||||||
|
## Copyright: 2008-2010, AprilHare, Darko Miletic <darko.miletic at gmail.com>
|
||||||
|
##
|
||||||
|
## Written: 2008
|
||||||
|
## Last Edited: Jan 2012
|
||||||
|
##
|
||||||
|
|
||||||
|
'''
|
||||||
|
01-19-2012: Added GrayScale Image conversion and Duplicant article removals
|
||||||
|
'''
|
||||||
|
|
||||||
|
__license__ = 'GNU General Public License v3 - http://www.gnu.org/copyleft/gpl.html'
|
||||||
|
__copyright__ = '2008-2012, AprilHare, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
__version__ = 'v0.5.0'
|
||||||
|
__date__ = '2012-01-19'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
newscientist.com
|
newscientist.com
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import urllib
|
import urllib
|
||||||
|
from calibre.utils.magick import Image
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
class NewScientist(BasicNewsRecipe):
|
class NewScientist(BasicNewsRecipe):
|
||||||
title = 'New Scientist - Online News w. subscription'
|
title = 'New Scientist - Online News w. subscription'
|
||||||
__author__ = 'Darko Miletic'
|
|
||||||
description = 'Science news and science articles from New Scientist.'
|
description = 'Science news and science articles from New Scientist.'
|
||||||
language = 'en'
|
language = 'en'
|
||||||
publisher = 'Reed Business Information Ltd.'
|
publisher = 'Reed Business Information Ltd.'
|
||||||
@ -39,10 +58,19 @@ class NewScientist(BasicNewsRecipe):
|
|||||||
|
|
||||||
keep_only_tags = [dict(name='div', attrs={'id':['pgtop','maincol','blgmaincol','nsblgposts','hldgalcols']})]
|
keep_only_tags = [dict(name='div', attrs={'id':['pgtop','maincol','blgmaincol','nsblgposts','hldgalcols']})]
|
||||||
|
|
||||||
|
# Whether to omit duplicates of articles (typically arsing when articles are indexed in
|
||||||
|
# more than one section). If True, only the first occurance will be downloaded.
|
||||||
|
filterDuplicates = True
|
||||||
|
|
||||||
|
# Whether to convert images to grayscale for eInk readers.
|
||||||
|
Convert_Grayscale = False
|
||||||
|
|
||||||
|
url_list = [] # This list is used to check if an article had already been included.
|
||||||
|
|
||||||
def get_browser(self):
|
def get_browser(self):
|
||||||
br = BasicNewsRecipe.get_browser()
|
br = BasicNewsRecipe.get_browser()
|
||||||
br.open('http://www.newscientist.com/')
|
br.open('http://www.newscientist.com/')
|
||||||
if self.username is not None and self.password is not None:
|
if self.username is not None and self.password is not None:
|
||||||
br.open('https://www.newscientist.com/user/login')
|
br.open('https://www.newscientist.com/user/login')
|
||||||
data = urllib.urlencode({ 'source':'form'
|
data = urllib.urlencode({ 'source':'form'
|
||||||
,'redirectURL':''
|
,'redirectURL':''
|
||||||
@ -80,6 +108,10 @@ class NewScientist(BasicNewsRecipe):
|
|||||||
return article.get('guid', None)
|
return article.get('guid', None)
|
||||||
|
|
||||||
def print_version(self, url):
|
def print_version(self, url):
|
||||||
|
if self.filterDuplicates:
|
||||||
|
if url in self.url_list:
|
||||||
|
return
|
||||||
|
self.url_list.append(url)
|
||||||
return url + '?full=true&print=true'
|
return url + '?full=true&print=true'
|
||||||
|
|
||||||
def preprocess_html(self, soup):
|
def preprocess_html(self, soup):
|
||||||
@ -91,7 +123,7 @@ class NewScientist(BasicNewsRecipe):
|
|||||||
item.name='p'
|
item.name='p'
|
||||||
for item in soup.findAll(['xref','figref']):
|
for item in soup.findAll(['xref','figref']):
|
||||||
tstr = item.string
|
tstr = item.string
|
||||||
item.replaceWith(tstr)
|
item.replaceWith(tstr)
|
||||||
for tg in soup.findAll('a'):
|
for tg in soup.findAll('a'):
|
||||||
if tg.string == 'Home':
|
if tg.string == 'Home':
|
||||||
tg.parent.extract()
|
tg.parent.extract()
|
||||||
@ -101,3 +133,16 @@ class NewScientist(BasicNewsRecipe):
|
|||||||
tg.replaceWith(tstr)
|
tg.replaceWith(tstr)
|
||||||
return soup
|
return soup
|
||||||
|
|
||||||
|
# Converts images to Gray Scale
|
||||||
|
def postprocess_html(self, soup, first):
|
||||||
|
if self.Convert_Grayscale:
|
||||||
|
#process all the images
|
||||||
|
for tag in soup.findAll(lambda tag: tag.name.lower()=='img' and tag.has_key('src')):
|
||||||
|
iurl = tag['src']
|
||||||
|
img = Image()
|
||||||
|
img.open(iurl)
|
||||||
|
if img < 0:
|
||||||
|
raise RuntimeError('Out of memory')
|
||||||
|
img.type = "GrayscaleType"
|
||||||
|
img.save(iurl)
|
||||||
|
return soup
|
||||||
|
46
recipes/the_daily_news_egypt.recipe
Normal file
46
recipes/the_daily_news_egypt.recipe
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2011, Pat Stapleton <pat.stapleton at gmail.com>'
|
||||||
|
'''
|
||||||
|
abc.net.au/news
|
||||||
|
'''
|
||||||
|
import re
|
||||||
|
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||||
|
|
||||||
|
class TheDailyNewsEG(BasicNewsRecipe):
|
||||||
|
title = u'The Daily News Egypt'
|
||||||
|
__author__ = 'Omm Mishmishah'
|
||||||
|
description = 'News from Egypt'
|
||||||
|
masthead_url = 'http://www.thedailynewsegypt.com/images/DailyNews-03_05.gif'
|
||||||
|
cover_url = 'http://www.thedailynewsegypt.com/images/DailyNews-03_05.gif'
|
||||||
|
|
||||||
|
auto_cleanup = True
|
||||||
|
oldest_article = 7
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
no_stylesheets = False
|
||||||
|
#delay = 1
|
||||||
|
use_embedded_content = False
|
||||||
|
encoding = 'utf8'
|
||||||
|
publisher = 'The Daily News Egypt'
|
||||||
|
category = 'News, Egypt, World'
|
||||||
|
language = 'en_EG'
|
||||||
|
publication_type = 'newsportal'
|
||||||
|
# preprocess_regexps = [(re.compile(r'<!--.*?-->', re.DOTALL), lambda m: '')]
|
||||||
|
#Remove annoying map links (inline-caption class is also used for some image captions! hence regex to match maps.google)
|
||||||
|
preprocess_regexps = [(re.compile(r'<a class="inline-caption" href="http://maps\.google\.com.*?/a>', re.DOTALL), lambda m: '')]
|
||||||
|
conversion_options = {
|
||||||
|
'comments' : description
|
||||||
|
,'tags' : category
|
||||||
|
,'language' : language
|
||||||
|
,'publisher' : publisher
|
||||||
|
,'linearize_tables': False
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_only_tags = [dict(attrs={'class':['article section']})]
|
||||||
|
|
||||||
|
remove_tags = [dict(attrs={'class':['related', 'tags', 'tools', 'attached-content ready',
|
||||||
|
'inline-content story left', 'inline-content map left contracted', 'published',
|
||||||
|
'story-map', 'statepromo', 'topics', ]})]
|
||||||
|
|
||||||
|
remove_attributes = ['width','height']
|
||||||
|
|
||||||
|
feeds = [(u'The Daily News Egypt', u'http://www.thedailynewsegypt.com/rss.php?sectionid=all')]
|
@ -3,7 +3,7 @@
|
|||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
<title>..:: calibre {library} ::.. {title}</title>
|
<title>..:: calibre {library} ::.. {title}</title>
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=100" />
|
<meta http-equiv="X-UA-Compatible" content="IE=100" />
|
||||||
<link rel="icon" type="image/x-icon" href="http://calibre-ebook.com/favicon.ico" />
|
<link rel="icon" type="image/x-icon" href="http://calibre-ebook.com/favicon.ico" />
|
||||||
@ -58,7 +58,7 @@
|
|||||||
method="post" title="Donate to support the development of calibre">
|
method="post" title="Donate to support the development of calibre">
|
||||||
<div>
|
<div>
|
||||||
<input type="hidden" name="cmd" value="_s-xclick"></input>
|
<input type="hidden" name="cmd" value="_s-xclick"></input>
|
||||||
<input type="hidden" name="hosted_button_id" value="3028915"></input>
|
<input type="hidden" name="hosted_button_id" value="MZQCP8EESW4H4"></input>
|
||||||
<input type="image"
|
<input type="image"
|
||||||
src="{prefix}/static/button-donate.png"
|
src="{prefix}/static/button-donate.png"
|
||||||
name="submit"></input>
|
name="submit"></input>
|
||||||
|
@ -26,7 +26,11 @@ def login_to_google(username, password):
|
|||||||
br.form['Email'] = username
|
br.form['Email'] = username
|
||||||
br.form['Passwd'] = password
|
br.form['Passwd'] = password
|
||||||
raw = br.submit().read()
|
raw = br.submit().read()
|
||||||
if b'<title>Account overview - Account Settings</title>' not in raw:
|
if re.search(br'<title>.*?Account Settings</title>', raw) is None:
|
||||||
|
x = re.search(br'(?is)<title>.*?</title>', raw)
|
||||||
|
if x is not None:
|
||||||
|
print ('Title of post login page: %s'%x.group())
|
||||||
|
#open('/tmp/goog.html', 'wb').write(raw)
|
||||||
raise ValueError(('Failed to login to google with credentials: %s %s'
|
raise ValueError(('Failed to login to google with credentials: %s %s'
|
||||||
'\nGoogle sometimes requires verification when logging in from a '
|
'\nGoogle sometimes requires verification when logging in from a '
|
||||||
'new IP address. Use lynx to login and supply the verification, '
|
'new IP address. Use lynx to login and supply the verification, '
|
||||||
|
@ -18,14 +18,14 @@ 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: 2012-01-08 20:03+0000\n"
|
"PO-Revision-Date: 2012-01-14 02:30+0000\n"
|
||||||
"Last-Translator: Simeon <Unknown>\n"
|
"Last-Translator: Wolfgang Rohdewald <wolfgang@rohdewald.de>\n"
|
||||||
"Language-Team: German <debian-l10n-german@lists.debian.org>\n"
|
"Language-Team: German <debian-l10n-german@lists.debian.org>\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: 2012-01-09 04:49+0000\n"
|
"X-Launchpad-Export-Date: 2012-01-15 05:18+0000\n"
|
||||||
"X-Generator: Launchpad (build 14640)\n"
|
"X-Generator: Launchpad (build 14664)\n"
|
||||||
"Language: de\n"
|
"Language: de\n"
|
||||||
|
|
||||||
#. name for aaa
|
#. name for aaa
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -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, 35)
|
numeric_version = (0, 8, 36)
|
||||||
__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>"
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ class ANDROID(USBMS):
|
|||||||
'GT-I5700', 'SAMSUNG', 'DELL', 'LINUX', 'GOOGLE', 'ARCHOS',
|
'GT-I5700', 'SAMSUNG', 'DELL', 'LINUX', 'GOOGLE', 'ARCHOS',
|
||||||
'TELECHIP', 'HUAWEI', 'T-MOBILE', 'SEMC', 'LGE', 'NVIDIA',
|
'TELECHIP', 'HUAWEI', 'T-MOBILE', 'SEMC', 'LGE', 'NVIDIA',
|
||||||
'GENERIC-', 'ZTE', 'MID', 'QUALCOMM', 'PANDIGIT', 'HYSTON',
|
'GENERIC-', 'ZTE', 'MID', 'QUALCOMM', 'PANDIGIT', 'HYSTON',
|
||||||
'VIZIO', 'GOOGLE', 'FREESCAL', 'KOBO_INC', 'LENOVO']
|
'VIZIO', 'GOOGLE', 'FREESCAL', 'KOBO_INC', 'LENOVO', 'ROCKCHIP']
|
||||||
WINDOWS_MAIN_MEM = ['ANDROID_PHONE', 'A855', 'A853', 'INC.NEXUS_ONE',
|
WINDOWS_MAIN_MEM = ['ANDROID_PHONE', 'A855', 'A853', 'INC.NEXUS_ONE',
|
||||||
'__UMS_COMPOSITE', '_MB200', 'MASS_STORAGE', '_-_CARD', 'SGH-I897',
|
'__UMS_COMPOSITE', '_MB200', 'MASS_STORAGE', '_-_CARD', 'SGH-I897',
|
||||||
'GT-I9000', 'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID',
|
'GT-I9000', 'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID',
|
||||||
@ -175,7 +175,7 @@ class ANDROID(USBMS):
|
|||||||
'GT-S5830_CARD', 'GT-S5570_CARD', 'MB870', 'MID7015A',
|
'GT-S5830_CARD', 'GT-S5570_CARD', 'MB870', 'MID7015A',
|
||||||
'ALPANDIGITAL', 'ANDROID_MID', 'VTAB1008', 'EMX51_BBG_ANDROI',
|
'ALPANDIGITAL', 'ANDROID_MID', 'VTAB1008', 'EMX51_BBG_ANDROI',
|
||||||
'UMS', '.K080', 'P990', 'LTE', 'MB853', 'GT-S5660_CARD', 'A107',
|
'UMS', '.K080', 'P990', 'LTE', 'MB853', 'GT-S5660_CARD', 'A107',
|
||||||
'GT-I9003_CARD', 'XT912', 'FILE-CD_GADGET']
|
'GT-I9003_CARD', 'XT912', 'FILE-CD_GADGET', 'RK29_SDK']
|
||||||
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', 'SAMSUNG_ANDROID', 'GT-P1000_CARD',
|
'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD',
|
||||||
'A70S', 'A101IT', '7', 'INCREDIBLE', 'A7EB', 'SGH-T849_CARD',
|
'A70S', 'A101IT', '7', 'INCREDIBLE', 'A7EB', 'SGH-T849_CARD',
|
||||||
|
@ -8,6 +8,7 @@ import StringIO, sys
|
|||||||
from struct import pack
|
from struct import pack
|
||||||
|
|
||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
|
from calibre import force_unicode
|
||||||
|
|
||||||
class StreamSlicer(object):
|
class StreamSlicer(object):
|
||||||
|
|
||||||
@ -245,7 +246,9 @@ class MetadataUpdater(object):
|
|||||||
def get_metadata(self):
|
def get_metadata(self):
|
||||||
''' Return MetaInformation with title, author'''
|
''' Return MetaInformation with title, author'''
|
||||||
self.get_original_metadata()
|
self.get_original_metadata()
|
||||||
return MetaInformation(self.metadata['Title'], [self.metadata['Authors']])
|
title = force_unicode(self.metadata['Title'], 'utf-8')
|
||||||
|
authors = force_unicode(self.metadata['Authors'], 'utf-8').split(';')
|
||||||
|
return MetaInformation(title, authors)
|
||||||
|
|
||||||
def get_original_metadata(self):
|
def get_original_metadata(self):
|
||||||
offset = self.base + self.topaz_headers['metadata']['blocks'][0]['offset']
|
offset = self.base + self.topaz_headers['metadata']['blocks'][0]['offset']
|
||||||
|
@ -102,7 +102,7 @@ viewport_to_document = (x, y, doc=window?.document) -> # {{{
|
|||||||
return [x, y]
|
return [x, y]
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
# Equivalent for caretRangeFromPoint for non WebKit browsers {{{
|
# Convert point to character offset {{{
|
||||||
range_has_point = (range, x, y) ->
|
range_has_point = (range, x, y) ->
|
||||||
for rect in range.getClientRects()
|
for rect in range.getClientRects()
|
||||||
if (rect.left <= x <= rect.right) and (rect.top <= y <= rect.bottom)
|
if (rect.left <= x <= rect.right) and (rect.top <= y <= rect.bottom)
|
||||||
|
@ -573,6 +573,9 @@ class SeriesIndexEdit(QDoubleSpinBox):
|
|||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
|
def reset_original(self):
|
||||||
|
self.original_series_name = self.series_edit.current_val
|
||||||
|
|
||||||
def break_cycles(self):
|
def break_cycles(self):
|
||||||
try:
|
try:
|
||||||
self.series_edit.currentIndexChanged.disconnect()
|
self.series_edit.currentIndexChanged.disconnect()
|
||||||
|
@ -376,6 +376,7 @@ class MetadataSingleDialogBase(ResizableDialog):
|
|||||||
if not mi.is_null('series') and mi.series.strip():
|
if not mi.is_null('series') and mi.series.strip():
|
||||||
self.series.current_val = mi.series
|
self.series.current_val = mi.series
|
||||||
if mi.series_index is not None:
|
if mi.series_index is not None:
|
||||||
|
self.series_index.reset_original()
|
||||||
self.series_index.current_val = float(mi.series_index)
|
self.series_index.current_val = float(mi.series_index)
|
||||||
if not mi.is_null('languages'):
|
if not mi.is_null('languages'):
|
||||||
langs = [canonicalize_lang(x) for x in mi.languages]
|
langs = [canonicalize_lang(x) for x in mi.languages]
|
||||||
|
@ -325,6 +325,7 @@ class Preferences(QMainWindow):
|
|||||||
return
|
return
|
||||||
rc = self.showing_widget.restart_critical
|
rc = self.showing_widget.restart_critical
|
||||||
self.committed = True
|
self.committed = True
|
||||||
|
do_restart = False
|
||||||
if must_restart:
|
if must_restart:
|
||||||
self.must_restart = True
|
self.must_restart = True
|
||||||
msg = _('Some of the changes you made require a restart.'
|
msg = _('Some of the changes you made require a restart.'
|
||||||
@ -335,12 +336,24 @@ class Preferences(QMainWindow):
|
|||||||
'set any more preferences, until you restart.')
|
'set any more preferences, until you restart.')
|
||||||
|
|
||||||
|
|
||||||
warning_dialog(self, _('Restart needed'), msg, show=True,
|
d = warning_dialog(self, _('Restart needed'), msg,
|
||||||
show_copy_button=False)
|
show_copy_button=False)
|
||||||
|
b = d.bb.addButton(_('Restart calibre now'), d.bb.AcceptRole)
|
||||||
|
b.setIcon(QIcon(I('lt.png')))
|
||||||
|
d.do_restart = False
|
||||||
|
def rf():
|
||||||
|
d.do_restart = True
|
||||||
|
b.clicked.connect(rf)
|
||||||
|
d.set_details('')
|
||||||
|
d.exec_()
|
||||||
|
b.clicked.disconnect()
|
||||||
|
do_restart = d.do_restart
|
||||||
self.showing_widget.refresh_gui(self.gui)
|
self.showing_widget.refresh_gui(self.gui)
|
||||||
self.hide_plugin()
|
self.hide_plugin()
|
||||||
if self.close_after_initial or (must_restart and rc):
|
if self.close_after_initial or (must_restart and rc) or do_restart:
|
||||||
self.close()
|
self.close()
|
||||||
|
if do_restart:
|
||||||
|
self.gui.quit(restart=True)
|
||||||
|
|
||||||
|
|
||||||
def cancel(self, *args):
|
def cancel(self, *args):
|
||||||
|
@ -497,7 +497,8 @@ class BrowseServer(object):
|
|||||||
xml(s, True),
|
xml(s, True),
|
||||||
xml(_('Loading, please wait'))+'…',
|
xml(_('Loading, please wait'))+'…',
|
||||||
unicode(c),
|
unicode(c),
|
||||||
xml(u'/browse/category_group/%s/%s'%(category,
|
xml(u'/browse/category_group/%s/%s'%(
|
||||||
|
hexlify(category.encode('utf-8')),
|
||||||
hexlify(s.encode('utf-8'))), True),
|
hexlify(s.encode('utf-8'))), True),
|
||||||
self.opts.url_prefix)
|
self.opts.url_prefix)
|
||||||
for s, c in category_groups.items()]
|
for s, c in category_groups.items()]
|
||||||
@ -531,6 +532,13 @@ class BrowseServer(object):
|
|||||||
sort = None
|
sort = None
|
||||||
if sort not in ('rating', 'name', 'popularity'):
|
if sort not in ('rating', 'name', 'popularity'):
|
||||||
sort = 'name'
|
sort = 'name'
|
||||||
|
try:
|
||||||
|
category = unhexlify(category)
|
||||||
|
if isbytestring(category):
|
||||||
|
category = category.decode('utf-8')
|
||||||
|
except:
|
||||||
|
raise cherrypy.HTTPError(404, 'invalid category')
|
||||||
|
|
||||||
categories = self.categories_cache()
|
categories = self.categories_cache()
|
||||||
if category not in categories:
|
if category not in categories:
|
||||||
raise cherrypy.HTTPError(404, 'category not found')
|
raise cherrypy.HTTPError(404, 'category not found')
|
||||||
|
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
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
@ -121,6 +121,7 @@ _extra_lang_codes = {
|
|||||||
'en_JP' : _('English (Japan)'),
|
'en_JP' : _('English (Japan)'),
|
||||||
'en_DE' : _('English (Germany)'),
|
'en_DE' : _('English (Germany)'),
|
||||||
'en_BG' : _('English (Bulgaria)'),
|
'en_BG' : _('English (Bulgaria)'),
|
||||||
|
'en_EG' : _('English (Egypt)'),
|
||||||
'en_NZ' : _('English (New Zealand)'),
|
'en_NZ' : _('English (New Zealand)'),
|
||||||
'en_CA' : _('English (Canada)'),
|
'en_CA' : _('English (Canada)'),
|
||||||
'en_GR' : _('English (Greece)'),
|
'en_GR' : _('English (Greece)'),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user