Sync to trunk.

This commit is contained in:
John Schember 2011-08-27 14:49:04 -04:00
commit 226bd0f871
91 changed files with 102053 additions and 48192 deletions

View File

@ -19,6 +19,90 @@
# new recipes:
# - title:
- version: 0.8.16
date: 2011-08-26
new features:
- title: "News download: Add algorithms to automatically clean up downloaded HTML"
description: "Use the algorithms from the Readability project to automatically cleanup downloaded HTML. You can turn this on in your own recipes by adding auto_cleanup=True to the recipe. It is turned on by default for basic recipes created via the GUI. This makes it a little easier to develop recipes for beginners."
type: major
- title: "Add an option to Preferences->Look and Feel->Cover Browser to show the cover browser full screen. When showing the cover browser in a separate window, you can make it fullscreen by pressing the F11 key."
tickets: [829855 ]
- title: "Show the languages currently used at the top of the drop down list of languages"
- title: "When automatically computing author sort from author's name, if the name contains certain words like Inc., Company, Team, etc. use the author name as the sort string directly. The list of such words can be controlled via Preferences->Tweaks."
tickets: [797895]
- title: "Add a search for individual tweaks to Preferences->Tweaks"
- title: "Drivers for a few new android phones"
bug fixes:
- title: "Fix line unwrapping algorithms to account for some central European characters as well."
tickets: [822744]
- title: "Switch to using more modern language names/translations from the iso-codes package"
- title: "Allow cases insensitive entering of language names for convenience."
tickets: [832761]
- title: "When adding a text indent to paragraphs as part of the remove spacing between paragraphs transformation, do not add an indent to paragraphs that are directly centered or right aligned."
tickets: [830439]
- title: "Conversion pipeline: More robust handling of case insensitive tag and class css selectors"
- title: "MOBI Output: Add support for the start attribute on <ol> tags"
- title: "When adding books that have no language specified, do not automatically set the language to calibre's interface language."
tickets: [830092]
- title: "Fix use of tag browser to search for languages when calibre is translated to a non English language"
tickets: [830078]
- title: "When downloading news, set the language field correctly"
- title: "Fix languages field in the Edit metadata dialog too wide"
tickets: [829912]
- title: "Fix setting of languages that have commas in their names broken"
- title: "FB2 Input: When convert FB2 files, read the cover from the FB2 file correctly."
tickets: [829240]
improved recipes:
- Politifact
- Reuters
- Sueddeutsche
- CNN
- Financial Times UK
- MSDN Magazine
- Houston Chronicle
- Harvard Business Review
new recipes:
- title: CBN News and Fairbanks Daily
author: by Roger
- title: Hacker News
author: Tom Scholl
- title: Various Turkish news sources
author: thomass
- title: Cvece Zla
author: Darko Miletic
- title: Various Polish news sources
author: fenuks
- title: Fluter
author: Armin Geller
- title: Brasil de Fato
author: Alex Mitrani
- version: 0.8.15
date: 2011-08-19

73
recipes/cbn.recipe Normal file
View File

@ -0,0 +1,73 @@
from calibre.web.feeds.news import BasicNewsRecipe
class CBN(BasicNewsRecipe):
title = u'CBN News'
__author__ = 'Roger'
# TODO: I just noticed this is downloading 25+ articles, while
# the online site is only publishing at most 7 articles daily.
# So, somehow this needs to be fixed it only downloads max 7 articles
oldest_article = 7
max_articles_per_feed = 100
description = 'The Christian Broadcasting Network'
publisher = 'http://www.cbn.com/'
category = 'news, religion, spiritual, christian'
language = 'en'
# Make article titles, author and date bold, italic or small font.
# TODO: Could use a smaller title text
# TODO: Italicize Author and Publisher?
#
# http://www.cbn.com/App_Themes/Common/base.css,
# http://www.cbn.com/App_Themes/CBNNews/article.css",
# ... and many more style sheets.
#extra_css = '''
# .story_item_headline { font-size: medium; font-weight: bold; }
# .story_item_author { font-size: small; font-style:italic; }
# .signature_line { font-size: small; }
# '''
remove_javascript = True
use_embedded_content = False
no_stylesheets = True
language = 'en'
encoding = 'iso-8859-1'
conversion_options = {'linearize_tables':True}
# TODO: No masterhead_url for CBN, using one I grepped from a news article
# (There's a better/higher contrast blue on white background image, but
# can't get it or it's too big -- embedded into a larger jpeg?)
masthead_url = 'http://www.cbn.com/templates/images/cbn_com_logo.jpg'
keep_only_tags = [
dict(name='h1', attrs={'id':'articleTitle'}),
dict(name='div', attrs={'class':'articleAuthor'}),
dict(name='div', attrs={'class':'articleDate'}),
dict(name='div', attrs={'class':'articleText'}),
]
remove_tags = [
# The article image is usually Adobe Flash Player Image
# The snapshot .jpg image files of the video are found
# within a URL folder named "PageFiles_Files"
# Filter this for now.
# (Majority of images seem to be Adobe Flash.)
dict(name='div', attrs={'class':'articleImage'}),
]
# Comment-out or uncomment any of the following RSS feeds according to your
# liking.
# A full list can be found here: http://www.cbn.com/rss.aspx
feeds = [
(u'World', u'http://www.cbn.com/cbnnews/world/feed/'),
(u'US', u'http://www.cbn.com/cbnnews/us/feed/'),
(u'Inside Israel', u'http://www.cbn.com/cbnnews/insideisrael/feed/'),
(u'Politics', u'http://www.cbn.com/cbnnews/politics/feed/'),
(u'Christian World News', u'http://www.cbn.com/cbnnews/shows/cwn/feed/'),
(u'Health and Science', u'http://www.cbn.com/cbnnews/healthscience/feed/'),
(u'Finance', u'http://www.cbn.com/cbnnews/finance/feed/'),
]

View File

@ -10,23 +10,23 @@ class FairbanksDailyNewsminer(BasicNewsRecipe):
publisher = 'http://www.newsminer.com/'
category = 'news, Alaska, Fairbanks'
language = 'en'
# Make article titles, author and date bold, italic or small font.
# http://assets.matchbin.com/sites/635/stylesheets/newsminer.com.css
# (signature_line contains date, views, comments)
extra_css = '''
extra_css = '''
.story_item_headline { font-size: medium; font-weight: bold; }
.story_item_author { font-size: small; font-style:italic; }
.signature_line { font-size: small; }
'''
remove_javascript = True
use_embedded_content = False
no_stylesheets = True
language = 'en'
encoding = 'utf8'
conversion_options = {'linearize_tables':True}
# TODO: The News-miner cover image seems a bit small. Can this be enlarged by 10-30%?
masthead_url = 'http://d2uh5w9wm14i0w.cloudfront.net/sites/635/assets/top_masthead_-_menu_pic.jpg'
@ -49,11 +49,11 @@ class FairbanksDailyNewsminer(BasicNewsRecipe):
#preprocess_regexps = [(re.compile(r'<span[^>]*addthis_separator*>'), lambda match: '') ]
#preprocess_regexps = [(re.compile(r'span class="addthis_separator">|</span>'), lambda match: '') ]
#preprocess_regexps = [
# (re.compile(r'<start>.*?<end>', re.IGNORECASE | re.DOTALL), lambda match : ''),
# ]
#def get_browser(self):
#def preprocess_html(soup, first_fetch):
# date = self.tag_to_string(soup.find('span', attrs={'class':'story_item_date updated'}))
@ -77,10 +77,10 @@ class FairbanksDailyNewsminer(BasicNewsRecipe):
dict(name='img', attrs={'class':'dont_touch_me'}),
dict(name='span', attrs={'class':'number_recommendations'}),
#dict(name='div', attrs={'class':'signature_line'}),
# Removes div within <!-- AddThis Button BEGIN --> <!-- AddThis Button END -->
dict(name='div', attrs={'class':'addthis_toolbox addthis_default_style'}),
dict(name='div', attrs={'class':'related_content'}),
dict(name='div', attrs={'id':'comments_container'})
]
@ -100,10 +100,10 @@ class FairbanksDailyNewsminer(BasicNewsRecipe):
(u'Politics', u'http://newsminer.com/rss/rss_feeds/politics_news?content_type=article&tags=politics_news&page_name=rss_feeds&instance=politics_news'),
(u'Sports', u'http://newsminer.com/rss/rss_feeds/sports_news?content_type=article&tags=sports_news&page_name=rss_feeds&instance=sports_news'),
(u'Latitude 65 feed', u'http://newsminer.com/rss/rss_feeds/latitude_65?content_type=article&tags=latitude_65&page_name=rss_feeds&offset=0&instance=latitude_65'),
(u'Sundays', u'http://newsminer.com/rss/rss_feeds/Sundays?content_type=article&tags=alaska_science_forum+scott_mccrea+interior_gardening+in_the_bush+judy_ferguson+book_reviews+theresa_bakker+judith_kleinfeld+interior_scrapbook+nuggets_comics+freeze_frame&page_name=rss_feeds&tag_inclusion=or&instance=Sundays'),
#(u'Sundays', u'http://newsminer.com/rss/rss_feeds/Sundays?content_type=article&tags=alaska_science_forum+scott_mccrea+interior_gardening+in_the_bush+judy_ferguson+book_reviews+theresa_bakker+judith_kleinfeld+interior_scrapbook+nuggets_comics+freeze_frame&page_name=rss_feeds&tag_inclusion=or&instance=Sundays'),
(u'Outdoors', u'http://newsminer.com/rss/rss_feeds/Outdoors?content_type=article&tags=outdoors&page_name=rss_feeds&instance=Outdoors'),
#(u'Fairbanks Grizzlies', u'http://newsminer.com/rss/rss_feeds/fairbanks_grizzlies?content_type=article&tags=fairbanks_grizzlies&page_name=rss_feeds&instance=fairbanks_grizzlies'),
(u'Newsminer', u'http://newsminer.com/rss/rss_feeds/Newsminer?content_type=article&tags=ted_stevens_bullets+ted_stevens+sports_news+business_news+fairbanks_grizzlies+dermot_cole_column+outdoors+alaska_science_forum+scott_mccrea+interior_gardening+in_the_bush+judy_ferguson+book_reviews+theresa_bakker+judith_kleinfeld+interior_scrapbook+nuggets_comics+freeze_frame&page_name=rss_feeds&tag_inclusion=or&instance=Newsminer'),
#(u'Newsminer', u'http://newsminer.com/rss/rss_feeds/Newsminer?content_type=article&tags=ted_stevens_bullets+ted_stevens+sports_news+business_news+fairbanks_grizzlies+dermot_cole_column+outdoors+alaska_science_forum+scott_mccrea+interior_gardening+in_the_bush+judy_ferguson+book_reviews+theresa_bakker+judith_kleinfeld+interior_scrapbook+nuggets_comics+freeze_frame&page_name=rss_feeds&tag_inclusion=or&instance=Newsminer'),
(u'Opinion', u'http://newsminer.com/rss/rss_feeds/Opinion?content_type=article&tags=editorials&page_name=rss_feeds&instance=Opinion'),
(u'Youth', u'http://newsminer.com/rss/rss_feeds/Youth?content_type=article&tags=youth&page_name=rss_feeds&instance=Youth'),
#(u'Dermot Cole Blog', u'http://newsminer.com/rss/rss_feeds/dermot_cole_blog+rss?content_type=blog+entry&sort_by=posted_on&user_ids=3015275&page_name=blogs_dermot_cole&limit=10&instance=dermot_cole_blog+rss'),

View File

@ -26,4 +26,7 @@ class PolitiFactCom(BasicNewsRecipe):
(u'Statements', u'http://www.politifact.com/feeds/statements/truth-o-meter/')
]
def get_browser(self):
br = BasicNewsRecipe.get_browser(self)
br.set_handle_gzip(True)
return br

View File

@ -16,23 +16,25 @@ class Reuters(BasicNewsRecipe):
remove_javascript = True
extra_css = '''
body{font-family:arial,helvetica,sans;}
body{font-family:arial,helvetica,sans;}
h1{ font-size:larger ; font-weight:bold; }
.byline{color:#006E97;font-size:x-small; font-weight:bold;}
.location{font-size:x-small; font-weight:bold;}
.timestamp{font-size:x-small; }
'''
'''
keep_only_tags = [dict(name='div', attrs={'class':'column2 gridPanel grid8'})]
remove_tags = [dict(name='div', attrs={'id':['recommendedArticles','relatedNews','relatedVideo','relatedFactboxes']}),
dict(name='p', attrs={'class':['relatedTopics']}),
dict(name='a', attrs={'id':['fullSizeLink']}),
dict(name='div', attrs={'class':['photoNav','relatedTopicButtons','articleComments','gridPanel grid8','footerHalf gridPanel grid1','gridPanel grid2','gridPanel grid3']}),]
dict(name='a', attrs={'id':['fullSizeLink']}),
dict(name='div', attrs={'class':['photoNav','relatedTopicButtons','articleComments','gridPanel grid8','footerHalf gridPanel grid1','gridPanel grid2','gridPanel grid3']}),
# Remove the Tweet, Share this, Email and Print links below article title too!
dict(name='div', attrs={'class':['columnRight']}),
]
preprocess_regexps = [ (re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
[
[
##(r'<HEAD>.*?</HEAD>' , lambda match : '<HEAD></HEAD>'),
(r'<div id="apple-rss-sidebar-background">.*?<!-- start Entries -->', lambda match : ''),
(r'<!-- end apple-rss-content-area -->.*?</body>', lambda match : '</body>'),
@ -40,18 +42,15 @@ class Reuters(BasicNewsRecipe):
(r'<body>.*?<div class="contentBand">', lambda match : '<body>'),
(r'<h3>Share:</h3>.*?</body>', lambda match : '<!-- END:: Shared Module id=36615 --></body>'),
(r'<div id="atools" class="articleTools">.*?<div class="linebreak">', lambda match : '<div class="linebreak">'),
]
]
]]
feeds = [ ('Top Stories', 'http://feeds.reuters.com/reuters/topNews?format=xml'),
('US News', 'http://feeds.reuters.com/reuters/domesticNews?format=xml'),
('World News', 'http://feeds.reuters.com/reuters/worldNews?format=xml'),
('Politics News', 'http://feeds.reuters.com/reuters/politicsNews?format=xml'),
('Science News', 'http://feeds.reuters.com/reuters/scienceNews?format=xml'),
('Environment News', 'http://feeds.reuters.com/reuters/Environment?format=xml'),
('Technology News', 'http://feeds.reuters.com/reuters/technologyNews?format=xml'),
('Oddly Enough News', 'http://feeds.reuters.com/reuters/oddlyEnoughNews?format=xml')
]
('US News', 'http://feeds.reuters.com/reuters/domesticNews?format=xml'),
('World News', 'http://feeds.reuters.com/reuters/worldNews?format=xml'),
('Politics News', 'http://feeds.reuters.com/reuters/politicsNews?format=xml'),
('Science News', 'http://feeds.reuters.com/reuters/scienceNews?format=xml'),
('Environment News', 'http://feeds.reuters.com/reuters/Environment?format=xml'),
('Technology News', 'http://feeds.reuters.com/reuters/technologyNews?format=xml'),
('Oddly Enough News', 'http://feeds.reuters.com/reuters/oddlyEnoughNews?format=xml')
]

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
@ -9,9 +10,9 @@ from calibre.web.feeds.news import BasicNewsRecipe
class Sueddeutsche(BasicNewsRecipe):
title = u'S\xfcddeutsche'
title = u'Süddeutsche'
description = 'News from Germany'
__author__ = 'Oliver Niesner and Sujata Raman'
__author__ = 'Oliver Niesner and Armin Geller'
use_embedded_content = False
timefmt = ' [%d %b %Y]'
oldest_article = 7
@ -25,13 +26,13 @@ class Sueddeutsche(BasicNewsRecipe):
remove_tags = [ dict(name='link'), dict(name='iframe'),
dict(name='div', attrs={'id':["bookmarking","themenbox","artikelfoot","CAD_AD",
"SKY_AD","NT1_AD","navbar1","sdesiteheader"]}),
"SKY_AD","NT1_AD","navbar1","sdesiteheader"]}),
dict(name='div', attrs={'class':["similar-article-box","artikelliste","nteaser301bg",
"pages closed","basebox right narrow","headslot galleried"]}),
"pages closed","basebox right narrow","headslot galleried"]}),
dict(name='div', attrs={'class':["articleDistractor","listHeader","listHeader2","hr2",
"item","videoBigButton","articlefooter full-column",
"item","videoBigButton","articlefooter full-column",
"bildbanderolle full-column","footerCopy padleft5"]}),
dict(name='p', attrs={'class':["ressortartikeln","artikelFliestext","entry-summary"]}),
@ -53,26 +54,29 @@ class Sueddeutsche(BasicNewsRecipe):
body{font-family:Arial,Helvetica,sans-serif; }
.photo {font-family:Arial,Helvetica,sans-serif; font-size: x-small; color: #666666;} '''
#feeds = [(u'Topthemen', u'http://suche.sueddeutsche.de/query/politik/-docdatetime/drilldown/%C2%A7documenttype%3AArtikel?output=rss')]
feeds = [(u'Wissen', u'http://suche.sueddeutsche.de/query/wissen/nav/%C2%A7ressort%3AWissen/sort/-docdatetime?output=rss'),
(u'Politik', u'http://suche.sueddeutsche.de/query/politik/nav/%C2%A7ressort%3APolitik/sort/-docdatetime?output=rss'),
(u'Wirtschaft', u'http://suche.sueddeutsche.de/query/wirtschaft/nav/%C2%A7ressort%3AWirtschaft/sort/-docdatetime?output=rss'),
(u'Finanzen', u'http://suche.sueddeutsche.de/query/finanzen/nav/%C2%A7ressort%3AGeld/sort/-docdatetime?output=rss'),
(u'Kultur', u'http://suche.sueddeutsche.de/query/kultur/nav/%C2%A7ressort%3AKultur/sort/-docdatetime?output=rss'),
(u'Sport', u'http://suche.sueddeutsche.de/query/sport/nav/%C2%A7ressort%3ASport/sort/-docdatetime?output=rss'),
(u'Bayern', u'http://suche.sueddeutsche.de/query/bayern/nav/%C2%A7ressort%3ABayern/sort/-docdatetime?output=rss'),
(u'Panorama', u'http://suche.sueddeutsche.de/query/panorama/sort/-docdatetime?output=rss'),
(u'Leben&Stil', u'http://suche.sueddeutsche.de/query/stil/nav/%C2%A7ressort%3A%22Leben%20%26%20Stil%22/sort/-docdatetime?output=rss'),
(u'Gesundheit', u'http://suche.sueddeutsche.de/query/gesundheit/nav/%C2%A7ressort%3AGesundheit/sort/-docdatetime?output=rss'),
(u'Auto&Reise', u'http://suche.sueddeutsche.de/query/automobil/nav/%C2%A7ressort%3A%22Auto%20%26%20Mobil%22/sort/-docdatetime?output=rss'),
(u'Computer', u'http://suche.sueddeutsche.de/query/computer/nav/%C2%A7ressort%3AComputer/sort/-docdatetime?output=rss'),
(u'Job&Karriere', u'http://suche.sueddeutsche.de/query/job/nav/%C2%A7ressort%3A%22Job%20%26%20Karriere%22/sort/-docdatetime?output=rss'),
(u'Reise', u'http://suche.sueddeutsche.de/query/reise/nav/%C2%A7ressort%3AReise/sort/-docdatetime?output=rss')
feeds = [
(u'Politik', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EPolitik%24?output=rss'),
(u'Wirtschaft', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EWirtschaft%24?output=rss'),
(u'Geld', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EGeld%24?output=rss'),
(u'Kultur', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EKultur%24?output=rss'),
(u'Sport', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5ESport%24?output=rss'),
(u'Leben', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5ELeben%24?output=rss'),
(u'Karriere', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EKarriere%24?output=rss'),
(u'München&Region', u'http://www.sueddeutsche.de/app/service/rss/ressort/muenchen/rss.xml'),
(u'Bayern', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EBayern%24?output=rss'),
(u'Medien', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EMedien%24?output=rss'),
(u'Digital', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EDigital%24?output=rss'),
(u'Auto', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EAuto%24?output=rss'),
(u'Wissen', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EWissen%24?output=rss'),
(u'Panorama', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EPanorama%24?output=rss'),
(u'Reise', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EReise%24?output=rss'),
(u'Technik', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5ETechnik%24?output=rss'), # sometimes only
(u'Macht', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EMacht%24?output=rss'), # sometimes only
(u'Job', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EJob%24?output=rss'), # sometimes only
(u'Service', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EService%24?output=rss'), # sometimes only
(u'Verlag', u'http://suche.sueddeutsche.de/query/%23/sort/-docdatetime/drilldown/%C2%A7ressort%3A%5EVerlag%24?output=rss'), # sometimes only
]
def print_version(self, url):
main, sep, id = url.rpartition('/')
return main + '/2.220/' + id

30845
setup/iso_639/iso_639_3.pot Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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, 15)
numeric_version = (0, 8, 16)
__version__ = u'.'.join(map(unicode, numeric_version))
__author__ = u"Kovid Goyal <kovid@kovidgoyal.net>"

View File

@ -984,7 +984,11 @@ OptionRecommendation(name='sr3_replace',
if fkey is None:
fkey = self.opts.dest.fkey
else:
fkey = map(float, fkey.split(','))
try:
fkey = map(float, fkey.split(','))
except:
self.log.error('Invalid font size key: %r ignoring'%fkey)
fkey = self.opts.dest.fkey
from calibre.ebooks.oeb.transforms.jacket import Jacket
Jacket()(self.oeb, self.opts, self.user_metadata)

View File

@ -67,7 +67,10 @@ class InterfaceAction(QObject):
#: Of the form: (text, icon_path, tooltip, keyboard shortcut)
#: icon, tooltip and keyboard shortcut can be None
#: shortcut must be a translated string if not None
#: shortcut must be a string, None or tuple of shortcuts.
#: If None, a keyboard shortcut corresponding to the action is not
#: registered. If you pass an empty tuple, then the shortcut is registered
#: with no default key binding.
action_spec = ('text', 'icon', None, None)
#: If True, a menu is automatically created and added to self.qaction
@ -117,7 +120,7 @@ class InterfaceAction(QObject):
bn = self.interface_action_base_plugin.name
return u'Interface Action: %s (%s)'%(bn, self.name)
def create_action(self, spec=None, attr='qaction'):
def create_action(self, spec=None, attr='qaction', shortcut_name=None):
if spec is None:
spec = self.action_spec
text, icon, tooltip, shortcut = spec
@ -143,12 +146,14 @@ class InterfaceAction(QObject):
if shortcut is not None:
keys = ((shortcut,) if isinstance(shortcut, basestring) else
tuple(shortcut))
if shortcut_name is None and spec[0]:
shortcut_name = unicode(spec[0])
if spec[0] and not (attr=='qaction' and self.popup_type ==
QToolButton.InstantPopup):
if shortcut_name and self.action_spec[0] and not (
attr == 'qaction' and self.popup_type == QToolButton.InstantPopup):
try:
self.gui.keyboard.register_shortcut(self.unique_name + ' - ' + attr,
unicode(spec[0]), default_keys=keys,
shortcut_name, default_keys=keys,
action=shortcut_action, description=desc,
group=self.action_spec[0])
except NameConflict as e:
@ -170,7 +175,32 @@ class InterfaceAction(QObject):
return action
def create_menu_action(self, menu, unique_name, text, icon=None, shortcut=None,
description=None, triggered=None):
description=None, triggered=None, shortcut_name=None):
'''
Convenience method to easily add actions to a QMenu.
:param menu: The QMenu the newly created action will be added to
:param unique_name: A unique name for this action, this must be
globally unique, so make it as descriptive as possible. If in doubt add
a uuid to it.
:param text: The text of the action.
:param icon: Either a QIcon or a file name. The file name is passed to
the I() builtin, so you do not need to pass the full path to the images
directory.
:param shortcut: A string, a list of strings, None or False. If False,
no keyboard shortcut is registered for this action. If None, a keyboard
shortcut with no default keybinding is registered. String and list of
strings register a shortcut with default keybinding as specified.
:param description: A description for this action. Used to set
tooltips.
:param triggered: A callable which is connected to the triggered signal
of the created action.
:param shortcut_name: The test displayed to the user when customizing
the keyboard shortcuts for this action. By default it is set to the
value of ``text``.
'''
if shortcut_name is None:
shortcut_name = unicode(text)
ac = menu.addAction(text)
if icon is not None:
if not isinstance(icon, QIcon):
@ -188,7 +218,7 @@ class InterfaceAction(QObject):
if shortcut is not False:
self.gui.keyboard.register_shortcut(unique_name,
unicode(text), default_keys=keys,
shortcut_name, default_keys=keys,
action=ac, description=description, group=self.action_spec[0])
if triggered is not None:
ac.triggered.connect(triggered)

View File

@ -11,7 +11,8 @@ class AddToLibraryAction(InterfaceAction):
name = 'Add To Library'
action_spec = (_('Add books to library'), 'add_book.png',
_('Add books to your calibre library from the connected device'), None)
_('Add books to your calibre library from the connected device'),
())
dont_add_to = frozenset(['menubar', 'toolbar', 'context-menu', 'toolbar-child'])
action_type = 'current'

View File

@ -17,7 +17,7 @@ from calibre.gui2.actions import InterfaceAction
class FetchAnnotationsAction(InterfaceAction):
name = 'Fetch Annotations'
action_spec = (_('Fetch annotations (experimental)'), None, None, None)
action_spec = (_('Fetch annotations (experimental)'), None, None, ())
dont_add_to = frozenset(['menubar', 'toolbar', 'context-menu', 'toolbar-child'])
action_type = 'current'

View File

@ -17,7 +17,7 @@ from calibre.gui2.actions import InterfaceAction
class GenerateCatalogAction(InterfaceAction):
name = 'Generate Catalog'
action_spec = (_('Create catalog'), 'catalog.png', 'Catalog builder', None)
action_spec = (_('Create catalog'), 'catalog.png', 'Catalog builder', ())
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
def genesis(self):

View File

@ -11,7 +11,7 @@ class EditCollectionsAction(InterfaceAction):
name = 'Edit Collections'
action_spec = (_('Manage collections'), None,
_('Manage the collections on this device'), None)
_('Manage the collections on this device'), ())
dont_add_to = frozenset(['menubar', 'toolbar', 'context-menu', 'toolbar-child'])
action_type = 'current'

View File

@ -15,7 +15,7 @@ from calibre.gui2.dialogs.plugin_updater import (PluginUpdaterDialog,
class PluginUpdaterAction(InterfaceAction):
name = 'Plugin Updater'
action_spec = (_('Plugin Updater'), None, None, None)
action_spec = (_('Plugin Updater'), None, None, ())
action_type = 'current'
def genesis(self):

View File

@ -14,7 +14,8 @@ from calibre.gui2.actions import InterfaceAction
class PickRandomAction(InterfaceAction):
name = 'Pick Random Book'
action_spec = (_('Pick a random book'), 'random.png', 'Catalog builder', None)
action_spec = (_('Pick a random book'), 'random.png',
'Select a random book from your calibre library', ())
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
def genesis(self):

View File

@ -307,6 +307,18 @@ class ConfigModel(QAbstractItemModel, SearchQueryParser):
return (self.index(ans[0], 0) if ans[1] < 0 else
self.index(ans[1], 0, self.index(ans[0], 0)))
def index_for_group(self, name):
for i in range(self.rowCount()):
node = self.data[i]
if node.data == name:
return self.index(i, 0)
@property
def group_names(self):
for i in range(self.rowCount()):
node = self.data[i]
yield node.data
# }}}
class Editor(QFrame): # {{{
@ -515,6 +527,7 @@ class Delegate(QStyledItemDelegate): # {{{
ckey = QKeySequence(ckey, QKeySequence.PortableText)
matched = False
for s in editor.all_shortcuts:
if s is editor.shortcut: continue
for k in s['keys']:
if k == ckey:
matched = True
@ -558,7 +571,8 @@ class ShortcutConfig(QWidget): # {{{
l.addWidget(self.view, 1, 0, 1, 3)
self.delegate = Delegate()
self.view.setItemDelegate(self.delegate)
self.delegate.sizeHintChanged.connect(self.scrollTo)
self.delegate.sizeHintChanged.connect(self.editor_opened,
type=Qt.QueuedConnection)
self.delegate.changed_signal.connect(self.changed_signal)
self.search = SearchBox2(self)
self.search.initialize('shortcuts_search_history',
@ -584,9 +598,8 @@ class ShortcutConfig(QWidget): # {{{
self._model = ConfigModel(keyboard, parent=self)
self.view.setModel(self._model)
def scrollTo(self, index):
if index is not None:
self.view.scrollTo(index, self.view.PositionAtTop)
def editor_opened(self, index):
self.view.scrollTo(index, self.view.EnsureVisible)
@property
def is_editing(self):
@ -631,6 +644,15 @@ class ShortcutConfig(QWidget): # {{{
unicode(self.search.currentText()), backwards=True)
self.highlight_index(idx)
def highlight_group(self, group_name):
idx = self.view.model().index_for_group(group_name)
if idx is not None:
self.view.expand(idx)
self.view.scrollTo(idx, self.view.PositionAtTop)
self.view.selectionModel().select(idx,
self.view.selectionModel().ClearAndSelect)
self.view.setCurrentIndex(idx)
self.view.setFocus(Qt.OtherFocusReason)
# }}}

View File

@ -37,6 +37,9 @@ class ConfigWidget(ConfigWidgetBase):
def refresh_gui(self, gui):
gui.keyboard.finalize()
def highligh_group(self, group_name):
self.conf_widget.highlight_group(group_name)
if __name__ == '__main__':
from PyQt4.Qt import QApplication
app = QApplication([])

View File

@ -34,11 +34,15 @@ The exact technique for enabling the proxy modules will vary depending on your A
RewriteEngine on
RewriteRule ^/calibre/(.*) http://localhost:8080/calibre/$1 [proxy]
RewriteRule ^/calibre http://localhost:8080 [proxy]
SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1
That's all, you will now be able to access the |app| Content Server under the /calibre URL in your apache server. The above rules pass all requests under /calibre to the calibre server running on port 8080 and thanks to the --url-prefix option above, the calibre server handles them transparently.
.. note:: If you are willing to devote an entire VirtualHost to the content server, then there is no need to use --url-prefix and RewriteRule, instead just use the ProxyPass directive.
.. note:: The server engine calibre uses, CherryPy, can have trouble with proxying and KeepAlive requests, so turn them off in Apache, with the SetEnv directives shown above.
In process
------------

View File

@ -63,7 +63,7 @@ You create the custom column in the usual way, using Preferences -> Add your own
.. image:: images/sg_cc.jpg
:align: center
Then after restarting |app|, you must tell |app| that the column is to be treated as a hierarchy. Go to Preferences -> Look and Feel and enter the lookup name "#genre" into the "Categories with hierarchical items" box. Press Apply, and you are done with setting up.
Then after restarting |app|, you must tell |app| that the column is to be treated as a hierarchy. Go to Preferences -> Look and Feel -> Tag Browser and enter the lookup name "#genre" into the "Categories with hierarchical items" box. Press Apply, and you are done with setting up.
.. image:: images/sg_pref.jpg
:align: center

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

18571
src/calibre/translations/gu.po Normal file

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