Merge from trunk

This commit is contained in:
Charles Haley 2012-06-16 11:21:34 +02:00
commit fa0afee166
101 changed files with 41230 additions and 38692 deletions

View File

@ -20,6 +20,57 @@
# - title:
- version: 0.8.56
date: 2012-06-15
new features:
- title: "Make the new calibre style default on Windows and OS X."
type: major
description: "This change gives a more 'modern' feel to the calibre user interface with focus highlighting, gradients, rounded corners, etc. In case you prefer the old look, you can restore under Preferences->Look & Feel->User interface style"
- title: "Get Books: Add the new SONY Reader store"
- title: "Read metadata from .docx (Microsoft Word) files"
- title: "Allow customizing the behavior of the searching for similar books by right clicking the book. You can now tell calibre to search different columns than the traditional author/series/publisher/tags/etc. in Preferences->Searching"
- title: "Add option to restore alternating row colors to the Tag Browser under Preferences->Look & Feel->Tag Browser"
- title: "Update to Qt 4.8.2 on windows compiled with link time code generation for a small performance boost"
bug fixes:
- title: "Get Books: Update plugins to handle website changes at ebooks.com, project gutenberg, and virtualo"
- title: "AZW3 Output: Fix TOC at start option not working"
- title: "AZW3 Output: Close self closing script/style/title/head tags explicitly as they cause problems in webkit based renderers like the Kindle Fire and calibre's viewers."
- title: "Fix the current_library_name() template function not updating after a library switch"
- title: "AZW3 Output: Handle the case of a link pointing to the last line of text in the document."
tickets: [1011330]
- title: "Fix regression in 0.8.55 that broke highlighting of items matching a search in the Tag Browser"
tickets: [1011030]
- title: "News download: Handle query only relative URLs"
improved recipes:
- Christian Science Monitor
- Neue Zurcher Zeitung
- Birmignham Post
- Metro UK
- New Musical Express
- The Independent
- The Daily Mirror
- Vreme
- Smithsonian Magazine
new recipes:
- title: NZZ Webpaper
author: Bernd Leinfelder
- version: 0.8.55
date: 2012-06-08

View File

@ -0,0 +1,47 @@
from calibre.web.feeds.news import BasicNewsRecipe
class HindustanTimes(BasicNewsRecipe):
title = u'Huffington Post UK'
language = 'en_GB'
__author__ = 'Krittika Goyal'
oldest_article = 2 #days
max_articles_per_feed = 25
#encoding = 'cp1252'
use_embedded_content = False
no_stylesheets = True
auto_cleanup = True
auto_cleanup_keep = '//div[@class="articleBody"]'
feeds = [
('UK Politics',
'http://www.huffingtonpost.com/feeds/verticals/uk-politics/news.xml'),
('UK Entertainment',
'http://www.huffingtonpost.com/feeds/verticals/uk-entertainment/news.xml'),
('UK Style',
'http://www.huffingtonpost.com/feeds/verticals/uk-style/news.xml'),
('UK Fashion:',
'http://www.huffingtonpost.com/feeds/verticals/uk-fashion/news.xml'),
('UK Universities:',
'http://www.huffingtonpost.com/feeds/verticals/uk-universities-education/news.xml'),
('UK World',
'http://www.huffingtonpost.com/feeds/verticals/uk-world/news.xml'),
('UK Lifestyle',
'http://www.huffingtonpost.com/feeds/verticals/uk-lifestyle/news.xml'),
('UK Comedy',
'http://www.huffingtonpost.com/feeds/verticals/uk-comedy/news.xml'),
('UK Celebrity',
'http://www.huffingtonpost.com/feeds/verticals/uk-celebrity/news.xml'),
('UK Culture',
'http://www.huffingtonpost.com/feeds/verticals/uk-culture/news.xml'),
('UK News',
'http://www.huffingtonpost.com/feeds/verticals/uk/news.xml'),
('UK Tech',
'http://www.huffingtonpost.com/feeds/verticals/uk-tech/news.xml'),
('UK Sport',
'http://www.huffingtonpost.com/feeds/verticals/uk-sport/news.xml'),
]
def get_article_url(self, entry):
if entry.links:
return entry.links[0]['href']
return BasicNewsRecipe.get_article_url(self, entry)

View File

@ -1,26 +1,42 @@
import re
from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import BeautifulSoup
class SmithsonianMagazine(BasicNewsRecipe):
title = u'Smithsonian Magazine'
language = 'en'
__author__ = 'Krittika Goyal'
__author__ = 'Krittika Goyal and TerminalVeracity'
oldest_article = 31#days
max_articles_per_feed = 50
use_embedded_content = False
#encoding = 'latin1'
recursions = 1
cover_url = 'http://sphotos.xx.fbcdn.net/hphotos-snc7/431147_10150602715983253_764313347_n.jpg'
match_regexps = ['&page=[2-9]$']
preprocess_regexps = [
(re.compile(r'for more of Smithsonian\'s coverage on history, science and nature.', re.DOTALL), lambda m: '')
]
extra_css = """
h1{font-size: large; margin: .2em 0}
h2{font-size: medium; margin: .2em 0}
h3{font-size: medium; margin: .2em 0}
#byLine{margin: .2em 0}
.articleImageCaptionwide{font-style: italic}
.wp-caption-text{font-style: italic}
img{display: block}
"""
remove_stylesheets = True
#remove_tags_before = dict(name='h1', attrs={'class':'heading'})
remove_tags_after = dict(name='p', attrs={'id':'articlePaginationWrapper'})
remove_tags_after = dict(name='div', attrs={'class':['post','articlePaginationWrapper']})
remove_tags = [
dict(name='iframe'),
dict(name='div', attrs={'class':'article_sidebar_border'}),
dict(name='div', attrs={'id':['article_sidebar_border', 'most-popular_large', 'most-popular-body_large']}),
##dict(name='ul', attrs={'class':'article-tools'}),
dict(name='div', attrs={'class':['article_sidebar_border','viewMorePhotos','addtoany_share_save_container','meta','social','OUTBRAIN','related-articles-inpage']}),
dict(name='div', attrs={'id':['article_sidebar_border', 'most-popular_large', 'most-popular-body_large','comment_section','article-related']}),
dict(name='ul', attrs={'class':'cat-breadcrumb col three last'}),
dict(name='h4', attrs={'id':'related-topics'}),
dict(name='table'),
dict(name='a', attrs={'href':['/subArticleBottomWeb','/subArticleTopWeb','/subArticleTopMag','/subArticleBottomMag']}),
dict(name='a', attrs={'name':'comments_shaded'}),
]
@ -39,15 +55,7 @@ class SmithsonianMagazine(BasicNewsRecipe):
def preprocess_html(self, soup):
story = soup.find(name='div', attrs={'id':'article-body'})
##td = heading.findParent(name='td')
##td.extract()
soup = BeautifulSoup('<html><head><title>t</title></head><body></body></html>')
body = soup.find(name='body')
body.insert(0, story)
return soup
#def postprocess_html(self, soup, first):
#for p in soup.findAll(id='articlePaginationWrapper'): p.extract()
#if not first:
#for div in soup.findAll(id='article-head'): div.extract()
#return soup

View File

@ -0,0 +1,95 @@
import re
from calibre.web.feeds.news import BasicNewsRecipe
class SomethingAwfulRecipe(BasicNewsRecipe):
title = 'Something Awful'
__author__ = 'atordo'
description = 'The Internet Makes You Stupid'
cover_url = 'http://i.somethingawful.com/core/head-logo-bluegren.png'
masthead_url = 'http://i.somethingawful.com/core/head-logo-bluegren.png'
oldest_article = 7
max_articles_per_feed = 50
auto_cleanup = False
no_stylesheets = True
remove_javascript = True
language = 'en'
use_embedded_content = False
remove_empty_feeds = True
publication_type = 'magazine'
recursions = 1
match_regexps = [r'\?page=\d+$']
preprocess_regexps = [
(re.compile(r'<!-- content end-->.*</body>', re.DOTALL), lambda match: '</body>')
]
remove_attributes = [ 'align', 'alt', 'valign' ]
keep_only_tags = [
dict(name='div', attrs={'class':'content_area'})
# ,dict(name='p', attrs={'class':'pagebar'})
]
remove_tags = [
dict(name='div', attrs={'class':['column_box','featurenav','social']})
,dict(name='div', attrs={'id':'sidebar'})
,dict(name='a', attrs={'class':'curpage'})
]
extra_css = '''
.byline{font-size:small} .font_big{font-size:large}
.compat5{font-weight:bold} .accentbox{background-color:#E3E3E3; border:solid black}
img{margin-bottom:0.4em; display:block; margin-left: auto; margin-right:auto}
'''
#feeds = [(u'Something Awful', u'http://www.somethingawful.com/rss/index.rss.xml')]
feeds = [
('Photoshop Phriday', 'http://www.somethingawful.com/rss/photoshop-phriday.rss.xml')
,('Comedy Goldmine', 'http://www.somethingawful.com/rss/comedy-goldmine.rss.xml')
#,('The Flash Tub', 'http://www.somethingawful.com/rss/flash-tub.rss.xml')
,('Awful Link of the Day', 'http://www.somethingawful.com/rss/awful-links.rss.xml')
,('Fake Something Awfuls', 'http://www.somethingawful.com/rss/fake-something-awful.rss.xml')
,('The Barbarian\'s Dojo', 'http://www.somethingawful.com/rss/steve-sumner.rss.xml')
,('The Great Goon Database', 'http://www.somethingawful.com/rss/great-goon-database.rss.xml')
,('Livejournal Theater', 'http://www.somethingawful.com/rss/livejournal-theater.rss.xml')
,('Joystick Token Healthpack', 'http://www.somethingawful.com/rss/token-healthpack.rss.xml')
#,('Webcam Ward', 'http://www.somethingawful.com/rss/webcam-ward.rss.xml')
,('Features / Articles', 'http://www.somethingawful.com/rss/feature-articles.rss.xml')
,('Guides', 'http://www.somethingawful.com/rss/guides.rss.xml')
,('Legal Threats', 'http://www.somethingawful.com/rss/legal-threats.rss.xml')
,('Pranks [ICQ]', 'http://www.somethingawful.com/rss/icq-pranks.rss.xml')
,('State Og', 'http://www.somethingawful.com/rss/state-og.rss.xml')
,('Everquest', 'http://www.somethingawful.com/rss/everquest.rss.xml')
,('Pranks [Email]', 'http://www.somethingawful.com/rss/email-pranks.rss.xml')
,('The Weekend Web', 'http://www.somethingawful.com/rss/weekend-web.rss.xml')
,('Daily Dirt', 'http://www.somethingawful.com/rss/daily-dirt.rss.xml')
,('The Art of Warcraft', 'http://www.somethingawful.com/rss/art-of-warcraft.rss.xml')
,('Video Game Article', 'http://www.somethingawful.com/rss/video-game-article.rss.xml')
,('The Awful Movie Database', 'http://www.somethingawful.com/rss/awful-movie-database.rss.xml')
#,('Downloads', 'http://www.somethingawful.com/rss/downloads.rss.xml')
,('Pregame Wrapup', 'http://www.somethingawful.com/rss/pregame-wrapup.rss.xml')
,('Second Life Safari', 'http://www.somethingawful.com/rss/second-life-safari.rss.xml')
,('The Hogosphere', 'http://www.somethingawful.com/rss/hogosphere.rss.xml')
,('Front Page News', 'http://www.somethingawful.com/rss/news.rss.xml')
,('Forum Friday\'s Monday', 'http://www.somethingawful.com/rss/forum-fridays.rss.xml')
,('Cliff Yablonski Hates You', 'http://www.somethingawful.com/rss/cliff-yablonski.rss.xml')
,('Manifestos From the Internet', 'http://www.somethingawful.com/rss/manifestos-from-internet.rss.xml')
,('Johnston Checks In', 'http://www.somethingawful.com/rss/levi-johnston.rss.xml')
,('Twitter Tuesday', 'http://www.somethingawful.com/rss/twitter-tuesday.rss.xml')
,('Music Article', 'http://www.somethingawful.com/rss/music-article.rss.xml')
,('Reviews [Games]', 'http://www.somethingawful.com/rss/game-reviews.rss.xml')
,('Reviews [Movies]', 'http://www.somethingawful.com/rss/movie-reviews.rss.xml')
,('Rom Pit', 'http://www.somethingawful.com/rss/rom-pit.rss.xml')
,('Truth Media [Reviews]', 'http://www.somethingawful.com/rss/truth-media-reviews.rss.xml')
,('Truth Media [Flames]', 'http://www.somethingawful.com/rss/truth-media-flames.rss.xml')
,('Awful Anime', 'http://www.somethingawful.com/rss/hentai-game-reviews.rss.xml')
,('The Horrors of Pornography', 'http://www.somethingawful.com/rss/horrors-of-porn.rss.xml')
,('Your Band Sucks', 'http://www.somethingawful.com/rss/your-band-sucks.rss.xml')
,('Fashion SWAT', 'http://www.somethingawful.com/rss/fashion-swat.rss.xml')
#,('AwfulVision', 'http://www.somethingawful.com/rss/awfulvision.rss.xml')
,('MMO Roulette', 'http://www.somethingawful.com/rss/mmo-roulette.rss.xml')
,('The Most Awful', 'http://www.somethingawful.com/rss/most-awful.rss.xml')
,('Garbage Day', 'http://www.somethingawful.com/rss/garbage-day.rss.xml')
,('WTF, D&D!?', 'http://www.somethingawful.com/rss/dungeons-and-dragons.rss.xml')
,('Current Releases', 'http://www.somethingawful.com/rss/current-movie-reviews.rss.xml')
]

View File

@ -1,5 +1,5 @@
__license__ = 'GPL v3'
__copyright__ = '2008-2009, Darko Miletic <darko.miletic at gmail.com>'
__copyright__ = '2008-2012, Darko Miletic <darko.miletic at gmail.com>'
'''
vreme.com
'''
@ -24,7 +24,17 @@ class Vreme(BasicNewsRecipe):
language = 'sr'
publication_type = 'magazine'
masthead_url = 'http://www.vreme.com/g/vreme-logo.gif'
extra_css = ' @font-face {font-family: "serif1";src:url(res:///opt/sony/ebook/FONT/tt0011m_.ttf)} body{font-family: serif1, serif} .article_description{font-family: serif1, serif} @font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)} .heading1{font-family: sans1, sans-serif; font-size: x-large; font-weight: bold} .heading2{font-family: sans1, sans-serif; font-size: large; font-weight: bold} .toc-heading{font-family: sans1, sans-serif; font-size: small} .column-heading2{font-family: sans1, sans-serif; font-size: large} .column-heading1{font-family: sans1, sans-serif; font-size: x-large} .column-normal{font-family: sans1, sans-serif; font-size: medium} .large{font-family: sans1, sans-serif; font-size: large} '
extra_css = """
@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)}
body{font-family: serif1, serif}
.article_description{font-family: serif1, serif}
.heading1{font-family: sans1, sans-serif; font-size: x-large; font-weight: bold} .heading2{font-family: sans1, sans-serif; font-size: large; font-weight: bold} .toc-heading{font-family: sans1, sans-serif; font-size: small}
.column-heading2{font-family: sans1, sans-serif; font-size: large}
.column-heading1{font-family: sans1, sans-serif; font-size: x-large}
.column-normal{font-family: sans1, sans-serif; font-size: medium}
.large{font-family: sans1, sans-serif; font-size: large}
"""
conversion_options = {
'comment' : description
@ -58,9 +68,12 @@ class Vreme(BasicNewsRecipe):
for item in soup.findAll(['h3','h4']):
description = u''
title_prefix = u''
feed_link = item.find('a')
if feed_link and feed_link.has_key('href') and feed_link['href'].startswith('/cms/view.php'):
url = self.INDEX + feed_link['href']
feed_link = item.find('a', href=True)
if feed_link and (feed_link['href'].startswith('cms/view.php') or feed_link['href'].startswith('/cms/view.php')):
if feed_link['href'].startswith('cms/view.php'):
url = self.INDEX + '/' + feed_link['href']
else:
url = self.INDEX + feed_link['href']
title = title_prefix + self.tag_to_string(feed_link)
date = strftime(self.timefmt)
articles.append({

Binary file not shown.

View File

@ -27,6 +27,7 @@ binary_includes = [
'/usr/lib/libwmflite-0.2.so.7',
'/usr/lib/liblcms.so.1',
'/usr/lib/liblzma.so.0',
'/usr/lib/libexpat.so.1',
'/usr/lib/libunrar.so',
'/usr/lib/libsqlite3.so.0',
'/usr/lib/libmng.so.1',

View File

@ -18,14 +18,14 @@ msgstr ""
"Report-Msgid-Bugs-To: Debian iso-codes team <pkg-isocodes-"
"devel@lists.alioth.debian.org>\n"
"POT-Creation-Date: 2011-11-25 14:01+0000\n"
"PO-Revision-Date: 2012-05-29 09:12+0000\n"
"Last-Translator: Moritz Höwer <moritzhoewermail@gmx.de>\n"
"PO-Revision-Date: 2012-06-10 11:16+0000\n"
"Last-Translator: SimonFS <simonschuette@arcor.de>\n"
"Language-Team: German <debian-l10n-german@lists.debian.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-05-30 05:20+0000\n"
"X-Generator: Launchpad (build 15316)\n"
"X-Launchpad-Export-Date: 2012-06-11 04:46+0000\n"
"X-Generator: Launchpad (build 15376)\n"
"Language: de\n"
#. name for aaa
@ -139,7 +139,7 @@ msgstr ""
#. name for abe
msgid "Abnaki; Western"
msgstr ""
msgstr "Abnaki; Westlich"
#. name for abf
msgid "Abai Sungai"

View File

@ -4,7 +4,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
__appname__ = u'calibre'
numeric_version = (0, 8, 55)
numeric_version = (0, 8, 56)
__version__ = u'.'.join(map(unicode, numeric_version))
__author__ = u"Kovid Goyal <kovid@kovidgoyal.net>"

View File

@ -169,6 +169,9 @@ class ANDROID(USBMS):
# Pantech
0x10a9 : { 0x6050 : [0x227] },
# Prestigio
0x2207 : { 0 : [0x222] },
}
EBOOK_DIR_MAIN = ['eBooks/import', 'wordplayer/calibretransfer', 'Books',
'sdcard/ebooks']
@ -182,7 +185,8 @@ class ANDROID(USBMS):
'TELECHIP', 'HUAWEI', 'T-MOBILE', 'SEMC', 'LGE', 'NVIDIA',
'GENERIC-', 'ZTE', 'MID', 'QUALCOMM', 'PANDIGIT', 'HYSTON',
'VIZIO', 'GOOGLE', 'FREESCAL', 'KOBO_INC', 'LENOVO', 'ROCKCHIP',
'POCKET', 'ONDA_MID', 'ZENITHIN', 'INGENIC', 'PMID701C', 'PD']
'POCKET', 'ONDA_MID', 'ZENITHIN', 'INGENIC', 'PMID701C', 'PD',
'PMP5097C']
WINDOWS_MAIN_MEM = ['ANDROID_PHONE', 'A855', 'A853', 'INC.NEXUS_ONE',
'__UMS_COMPOSITE', '_MB200', 'MASS_STORAGE', '_-_CARD', 'SGH-I897',
'GT-I9000', 'FILE-STOR_GADGET', 'SGH-T959_CARD', 'SGH-T959', 'SAMSUNG_ANDROID',
@ -198,7 +202,7 @@ class ANDROID(USBMS):
'GT-I9003_CARD', 'XT912', 'FILE-CD_GADGET', 'RK29_SDK', 'MB855',
'XT910', 'BOOK_A10', 'USB_2.0_DRIVER', 'I9100T', 'P999DW',
'KTABLET_PC', 'INGENIC', 'GT-I9001_CARD', 'USB_2.0_DRIVER',
'GT-S5830L_CARD', 'UNIVERSE', 'XT875']
'GT-S5830L_CARD', 'UNIVERSE', 'XT875', 'PRO']
WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897',
'FILE-STOR_GADGET', 'SGH-T959_CARD', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD',
'A70S', 'A101IT', '7', 'INCREDIBLE', 'A7EB', 'SGH-T849_CARD',
@ -207,7 +211,7 @@ class ANDROID(USBMS):
'A1-07___C0541A4F', 'XT912', 'MB855', 'XT910', 'BOOK_A10_CARD',
'USB_2.0_DRIVER', 'I9100T', 'P999DW_SD_CARD', 'KTABLET_PC',
'FILE-CD_GADGET', 'GT-I9001_CARD', 'USB_2.0_DRIVER', 'XT875',
'UMS_COMPOSITE']
'UMS_COMPOSITE', 'PRO']
OSX_MAIN_MEM = 'Android Device Main Memory'

View File

@ -446,7 +446,7 @@ class HTMLPreProcessor(object):
# Remove page links
(re.compile(r'<a name=\d+></a>', re.IGNORECASE), lambda match: ''),
# Remove <hr> tags
(re.compile(r'<hr.*?>', re.IGNORECASE), lambda match: '<br>'),
(re.compile(r'<hr.*?>', re.IGNORECASE), lambda match: ''),
# Remove gray background
(re.compile(r'<BODY[^<>]+>'), lambda match : '<BODY>'),

View File

@ -108,6 +108,7 @@ gprefs.defaults['blocked_auto_formats'] = []
gprefs.defaults['auto_add_auto_convert'] = True
gprefs.defaults['ui_style'] = 'calibre' if iswindows or isosx else 'system'
gprefs.defaults['tag_browser_old_look'] = False
gprefs.defaults['book_list_tooltips'] = True
# }}}
NONE = QVariant() #: Null value to return from the data function of item models

View File

@ -12,8 +12,8 @@ from PyQt4.Qt import QPixmap, SIGNAL
from calibre.gui2 import choose_images, error_dialog
from calibre.gui2.convert.metadata_ui import Ui_Form
from calibre.ebooks.metadata import authors_to_string, string_to_authors, \
MetaInformation
from calibre.ebooks.metadata import (authors_to_string, string_to_authors,
MetaInformation, title_sort)
from calibre.ebooks.metadata.opf2 import metadata_to_opf
from calibre.ptempfile import PersistentTemporaryFile
from calibre.gui2.convert import Widget
@ -230,9 +230,19 @@ class MetadataWidget(Widget, Ui_Form):
Both may be None. Also returns a recommendation dictionary.
'''
recs = self.commit_options(save_defaults)
self.user_mi = self.get_metadata()
self.user_mi = mi = self.get_metadata()
self.cover_file = self.opf_file = None
if self.db is not None:
if mi.title == self.db.title(self.book_id, index_is_id=True):
mi.title_sort = self.db.title_sort(self.book_id, index_is_id=True)
else:
# Regenerate title sort taking into account book language
languages = self.db.languages(self.book_id, index_is_id=True)
if languages:
lang = languages.split(',')[0]
else:
lang = None
mi.title_sort = title_sort(mi.title, lang=lang)
self.db.set_metadata(self.book_id, self.user_mi)
self.mi, self.opf_file = create_opf_file(self.db, self.book_id)
if self.cover_changed and self.cover_data is not None:

View File

@ -68,6 +68,7 @@ class DeleteMatchingFromDeviceDialog(QDialog, Ui_DeleteMatchingFromDeviceDialog)
'<b>permanently deleted</b> from your '
'device. Please verify the list.')+'</p>')
self.buttonBox.accepted.connect(self.accepted)
self.buttonBox.rejected.connect(self.rejected)
self.table.cellClicked.connect(self.cell_clicked)
self.table.setSelectionMode(QAbstractItemView.NoSelection)
self.table.setColumnCount(7)

View File

@ -312,7 +312,7 @@ class %(classname)s(%(base_class)s):
item = items[-1]
id_ = unicode(item.data(Qt.UserRole).toString())
title = unicode(item.data(Qt.DisplayRole).toString()).rpartition(' [')[0]
profile = get_builtin_recipe_by_id(id_)
profile = get_builtin_recipe_by_id(id_, download_recipe=True)
if profile is None:
raise Exception('Something weird happened')

View File

@ -82,6 +82,11 @@ class BooksView(QTableView): # {{{
files_dropped = pyqtSignal(object)
add_column_signal = pyqtSignal()
def viewportEvent(self, event):
if (event.type() == event.ToolTip and not gprefs['book_list_tooltips']):
return False
return QTableView.viewportEvent(self, event)
def __init__(self, parent, modelcls=BooksModel, use_edit_metadata_dialog=True):
QTableView.__init__(self, parent)

View File

@ -104,6 +104,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
r('ui_style', gprefs, restart_required=True, choices=
[(_('System default'), 'system'), (_('Calibre style'),
'calibre')])
r('book_list_tooltips', gprefs)
r('tag_browser_old_look', gprefs, restart_required=True)
r('cover_flow_queue_length', config, restart_required=True)

View File

@ -105,7 +105,7 @@
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<item row="7" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>&amp;Toolbar</string>
@ -140,7 +140,7 @@
</layout>
</widget>
</item>
<item row="7" column="0">
<item row="8" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -153,7 +153,7 @@
</property>
</spacer>
</item>
<item row="5" column="0">
<item row="6" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_2">
@ -174,7 +174,7 @@
</item>
</layout>
</item>
<item row="5" column="1">
<item row="6" column="1">
<widget class="QPushButton" name="change_font_button">
<property name="text">
<string>Change &amp;font (needs restart)</string>
@ -194,6 +194,13 @@
<item row="0" column="1">
<widget class="QComboBox" name="opt_ui_style"/>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="opt_book_list_tooltips">
<property name="text">
<string>Show &amp;tooltips in the book list</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">

View File

@ -5,6 +5,7 @@ __license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import textwrap
from calibre.gui2.preferences import ConfigWidgetBase, test_widget, Setting
from calibre.gui2.preferences.misc_ui import Ui_Form
@ -31,6 +32,11 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
r('worker_limit', config, restart_required=True, setting=WorkersSetting)
r('enforce_cpu_limit', config, restart_required=True)
r('worker_max_time', gprefs)
self.opt_worker_limit.setToolTip(textwrap.fill(
_('The maximum number of jobs that will run simultaneously in '
'the background. This refers to CPU intensive tasks like '
' conversion. Lower this number'
' if you want calibre to use less CPU.')))
self.device_detection_button.clicked.connect(self.debug_device_detection)
self.button_open_config_dir.clicked.connect(self.open_config_dir)
self.user_defined_device_button.clicked.connect(self.user_defined_device)

View File

@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
import random
import re
import urllib2
import urllib
from contextlib import closing
from lxml import html
@ -47,7 +47,7 @@ class EbookscomStore(BasicStoreConfig, StorePlugin):
d.exec_()
def search(self, query, max_results=10, timeout=60):
url = 'http://www.ebooks.com/SearchApp/SearchResults.net?term=' + urllib2.quote(query)
url = 'http://www.ebooks.com/SearchApp/SearchResults.net?term=' + urllib.quote_plus(query)
br = browser()
@ -66,15 +66,12 @@ class EbookscomStore(BasicStoreConfig, StorePlugin):
cover_url = ''.join(data.xpath('.//div[@class="img"]//img/@src'))
title = ''
author = ''
header_parts = data.xpath('.//div[@class="descr"]/h4//a//text()')
if header_parts:
title = header_parts[0]
header_parts = header_parts[1:]
if header_parts:
author = ', '.join(header_parts)
title = ''.join(data.xpath(
'descendant::span[@class="book-title"]/a/text()')).strip()
author = ''.join(data.xpath(
'descendant::span[@class="author"]/a/text()')).strip()
if not title or not author:
continue
counter -= 1

View File

@ -48,13 +48,9 @@ class SonyStore(BasicStoreConfig, StorePlugin):
break
curr = ''.join(item.xpath('descendant::div[@class="pricing"]/descendant::*[@class="currency"]/@title')).strip()
if not curr:
curr = 'USD'
amt = ''.join(item.xpath('descendant::div[@class="pricing"]/descendant::*[@class="amount"]/text()')).strip()
if not amt:
amt = '0'
s = SearchResult()
s.price = curr+' '+amt
s.price = (curr+' '+amt) if (curr and amt) else _('Not Available')
title = item.xpath('descendant::h3[@class="item"]')
if not title: continue
title = etree.tostring(title[0], method='text',

View File

@ -574,6 +574,9 @@ def command_set_metadata(args, dbpath):
if len(args) > 2:
opf = args[2]
if not os.path.exists(opf):
prints(_('The OPF file %s does not exist')%opf, file=sys.stderr)
return 1
do_set_metadata(db, book_id, opf)
if opts.field:

View File

@ -102,7 +102,12 @@ class AuthController(object):
@wraps(func)
def authenticate(*args, **kwargs):
cookie = cherrypy.request.cookie.get(self.cookie_name, None)
if not (allow_cookie_auth and self.is_valid(cookie)):
ua = cherrypy.request.headers.get('User-Agent', '').strip()
if ('iPad;' in ua or 'iPhone;' in ua or (
not (allow_cookie_auth and self.is_valid(cookie)))):
# Apparently the iPad cant handle this
# see https://bugs.launchpad.net/bugs/1013976
digest_auth(self.realm, get_ha1_dict_plain(self.users_dict),
self.secret)

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

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