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
4daefc5575
@ -45,9 +45,11 @@ class PluginWidget(Widget, Ui_Form):
|
||||
def set_value_handler(self, g, val):
|
||||
if unicode(g.objectName()) in ('opt_serif_family',
|
||||
'opt_sans_family', 'opt_mono_family'):
|
||||
idx = g.findText(val, Qt.MatchFixedString)
|
||||
idx = -1
|
||||
if val:
|
||||
idx = g.findText(val, Qt.MatchFixedString)
|
||||
if idx < 0:
|
||||
idx = 0
|
||||
g.setCurrentIndex(0)
|
||||
g.setCurrentIndex(idx)
|
||||
return True
|
||||
return False
|
||||
|
@ -20,6 +20,36 @@
|
||||
<string>Book Cover</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="_3">
|
||||
<item>
|
||||
<widget class="ImageView" name="cover">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../images.qrc">:/images/book.svg</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="opt_prefer_metadata_cover">
|
||||
<property name="text">
|
||||
<string>Use cover from &source file</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QVBoxLayout" name="_4">
|
||||
<property name="spacing">
|
||||
@ -71,36 +101,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="opt_prefer_metadata_cover">
|
||||
<property name="text">
|
||||
<string>Use cover from &source file</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="_3">
|
||||
<item>
|
||||
<widget class="ImageView" name="cover">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../images.qrc">:/images/book.svg</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>opt_prefer_metadata_cover</zorder>
|
||||
<zorder></zorder>
|
||||
@ -329,6 +329,19 @@
|
||||
<header>widgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>title</tabstop>
|
||||
<tabstop>author</tabstop>
|
||||
<tabstop>author_sort</tabstop>
|
||||
<tabstop>publisher</tabstop>
|
||||
<tabstop>tags</tabstop>
|
||||
<tabstop>series</tabstop>
|
||||
<tabstop>series_index</tabstop>
|
||||
<tabstop>comment</tabstop>
|
||||
<tabstop>cover_path</tabstop>
|
||||
<tabstop>cover_button</tabstop>
|
||||
<tabstop>opt_prefer_metadata_cover</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../images.qrc"/>
|
||||
<include location="../images.qrc"/>
|
||||
|
@ -43,8 +43,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>869</width>
|
||||
<height>696</height>
|
||||
<width>879</width>
|
||||
<height>710</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
@ -121,6 +121,9 @@
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>authors</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
@ -661,26 +664,28 @@
|
||||
<tabstops>
|
||||
<tabstop>title</tabstop>
|
||||
<tabstop>swap_button</tabstop>
|
||||
<tabstop>authors</tabstop>
|
||||
<tabstop>author_sort</tabstop>
|
||||
<tabstop>auto_author_sort</tabstop>
|
||||
<tabstop>rating</tabstop>
|
||||
<tabstop>publisher</tabstop>
|
||||
<tabstop>tags</tabstop>
|
||||
<tabstop>series</tabstop>
|
||||
<tabstop>tag_editor_button</tabstop>
|
||||
<tabstop>series</tabstop>
|
||||
<tabstop>remove_series_button</tabstop>
|
||||
<tabstop>series_index</tabstop>
|
||||
<tabstop>isbn</tabstop>
|
||||
<tabstop>pubdate</tabstop>
|
||||
<tabstop>comments</tabstop>
|
||||
<tabstop>fetch_metadata_button</tabstop>
|
||||
<tabstop>fetch_cover_button</tabstop>
|
||||
<tabstop>formats</tabstop>
|
||||
<tabstop>add_format_button</tabstop>
|
||||
<tabstop>remove_format_button</tabstop>
|
||||
<tabstop>button_set_cover</tabstop>
|
||||
<tabstop>remove_format_button</tabstop>
|
||||
<tabstop>cover_path</tabstop>
|
||||
<tabstop>cover_button</tabstop>
|
||||
<tabstop>reset_cover</tabstop>
|
||||
<tabstop>fetch_cover_button</tabstop>
|
||||
<tabstop>scrollArea</tabstop>
|
||||
<tabstop>button_box</tabstop>
|
||||
</tabstops>
|
||||
|
@ -152,10 +152,20 @@ def convert_bulk_ebook(parent, db, book_ids, out_format=None):
|
||||
|
||||
def fetch_scheduled_recipe(recipe, script):
|
||||
from calibre.gui2.dialogs.scheduler import config
|
||||
from calibre.ebooks.conversion.config import load_defaults
|
||||
fmt = prefs['output_format'].lower()
|
||||
pt = PersistentTemporaryFile(suffix='_recipe_out.%s'%fmt.lower())
|
||||
pt.close()
|
||||
recs = []
|
||||
ps = load_defaults('page_setup')
|
||||
if 'output_profile' in ps:
|
||||
recs.append(('output_profile', ps['output_profile'],
|
||||
OptionRecommendation.HIGH))
|
||||
lf = load_defaults('look_and_feel')
|
||||
if lf.get('base_font_size', 0.0) != 0.0:
|
||||
recs.append(('base_font_size', ps['base_font_size'],
|
||||
OptionRecommendation.HIGH))
|
||||
|
||||
args = [script, pt.name, recs]
|
||||
if recipe.needs_subscription:
|
||||
x = config.get('recipe_account_info_%s'%recipe.id, False)
|
||||
|
@ -490,13 +490,13 @@ class LineEditECM(object):
|
||||
|
||||
|
||||
class EnLineEdit(LineEditECM, QLineEdit):
|
||||
|
||||
|
||||
'''
|
||||
Enhanced QLineEdit.
|
||||
|
||||
|
||||
Includes an extended content menu.
|
||||
'''
|
||||
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@ -593,6 +593,13 @@ class EnComboBox(QComboBox):
|
||||
def text(self):
|
||||
return qstring_to_unicode(self.currentText())
|
||||
|
||||
def setText(self, text):
|
||||
idx = self.findText(text, Qt.MatchFixedString)
|
||||
if idx == -1:
|
||||
self.insertItem(0, text)
|
||||
idx = 0
|
||||
self.setCurrentIndex(idx)
|
||||
|
||||
class PythonHighlighter(QSyntaxHighlighter):
|
||||
|
||||
Rules = []
|
||||
|
@ -16,7 +16,7 @@ class Article(object):
|
||||
|
||||
time_offset = datetime.now() - datetime.utcnow()
|
||||
|
||||
def __init__(self, id, title, url, summary, published, content):
|
||||
def __init__(self, id, title, url, author, summary, published, content):
|
||||
self.downloaded = False
|
||||
self.id = id
|
||||
self.title = title.strip() if title else title
|
||||
@ -26,6 +26,9 @@ class Article(object):
|
||||
except:
|
||||
pass
|
||||
self.url = url
|
||||
self.author = author
|
||||
if author and not isinstance(author, unicode):
|
||||
author = author.decode('utf-8', 'replace')
|
||||
self.summary = summary
|
||||
if summary and not isinstance(summary, unicode):
|
||||
summary = summary.decode('utf-8', 'replace')
|
||||
@ -39,6 +42,7 @@ class Article(object):
|
||||
traceback.print_exc()
|
||||
summary = u''
|
||||
self.text_summary = summary
|
||||
self.author = author
|
||||
self.content = content
|
||||
self.date = published
|
||||
self.utctime = datetime(*self.date[:6])
|
||||
@ -50,10 +54,11 @@ class Article(object):
|
||||
(u'''\
|
||||
Title : %s
|
||||
URL : %s
|
||||
Author : %s
|
||||
Summary : %s
|
||||
Date : %s
|
||||
Has content : %s
|
||||
'''%(self.title, self.url, self.summary[:20]+'...', self.localtime.strftime('%a, %d %b, %Y %H:%M'),
|
||||
'''%(self.title, self.url, self.author, self.summary[:20]+'...', self.localtime.strftime('%a, %d %b, %Y %H:%M'),
|
||||
bool(self.content))).encode('utf-8')
|
||||
|
||||
def __str__(self):
|
||||
@ -124,7 +129,8 @@ class Feed(object):
|
||||
link = item.get('url', None)
|
||||
description = item.get('description', '')
|
||||
content = item.get('content', '')
|
||||
article = Article(id, title, link, description, published, content)
|
||||
author = item.get('author', '')
|
||||
article = Article(id, title, link, author, description, published, content)
|
||||
delta = datetime.utcnow() - article.utctime
|
||||
if delta.days*24*3600 + delta.seconds <= 24*3600*self.oldest_article:
|
||||
self.articles.append(article)
|
||||
@ -149,7 +155,9 @@ class Feed(object):
|
||||
self.logger.warning('Failed to get link for %s'%title)
|
||||
self.logger.debug(traceback.format_exc())
|
||||
link = None
|
||||
|
||||
description = item.get('summary', None)
|
||||
author = item.get('author', None)
|
||||
|
||||
content = [i.value for i in item.get('content', []) if i.value]
|
||||
content = [i if isinstance(i, unicode) else i.decode('utf-8', 'replace')
|
||||
@ -159,7 +167,7 @@ class Feed(object):
|
||||
content = None
|
||||
if not link and not content:
|
||||
return
|
||||
article = Article(id, title, link, description, published, content)
|
||||
article = Article(id, title, link, author, description, published, content)
|
||||
delta = datetime.utcnow() - article.utctime
|
||||
if delta.days*24*3600 + delta.seconds <= 24*3600*self.oldest_article:
|
||||
self.articles.append(article)
|
||||
|
@ -884,6 +884,9 @@ class BasicNewsRecipe(Recipe):
|
||||
for j, a in enumerate(f):
|
||||
if getattr(a, 'downloaded', False):
|
||||
adir = 'feed_%d/article_%d/'%(num, j)
|
||||
auth = a.author
|
||||
if not auth:
|
||||
auth = None
|
||||
desc = a.text_summary
|
||||
if not desc:
|
||||
desc = None
|
||||
@ -893,7 +896,7 @@ class BasicNewsRecipe(Recipe):
|
||||
self.play_order_counter += 1
|
||||
po = self.play_order_counter
|
||||
parent.add_item('%sindex.html'%adir, None, a.title if a.title else _('Untitled Article'),
|
||||
play_order=po, description=desc)
|
||||
play_order=po, author=auth, description=desc)
|
||||
last = os.path.join(self.output_dir, ('%sindex.html'%adir).replace('/', os.sep))
|
||||
for sp in a.sub_pages:
|
||||
prefix = os.path.commonprefix([opf_path, sp])
|
||||
@ -925,11 +928,15 @@ class BasicNewsRecipe(Recipe):
|
||||
if po is None:
|
||||
self.play_order_counter += 1
|
||||
po = self.play_order_counter
|
||||
auth = getattr(f, 'author', None)
|
||||
if not auth:
|
||||
auth = None
|
||||
desc = getattr(f, 'description', None)
|
||||
if not desc:
|
||||
desc = None
|
||||
feed_index(i, toc.add_item('feed_%d/index.html'%i, None,
|
||||
f.title, play_order=po, description=desc))
|
||||
f.title, play_order=po, description=desc, author=auth))
|
||||
|
||||
else:
|
||||
entries.append('feed_%d/index.html'%0)
|
||||
feed_index(0, toc)
|
||||
|
@ -9,13 +9,26 @@ from calibre.web.feeds.news import BasicNewsRecipe
|
||||
class Newsweek(BasicNewsRecipe):
|
||||
|
||||
title = 'Newsweek'
|
||||
__author__ = 'Kovid Goyal'
|
||||
__author__ = 'Kovid Goyal and Sujata Raman'
|
||||
description = 'Weekly news and current affairs in the US'
|
||||
no_stylesheets = True
|
||||
|
||||
extra_css = '''
|
||||
h1{color:#383733;font-family:Arial,Helvetica,sans-serif;font-size:large;}
|
||||
.deck{font-family:Georgia,"Century Schoolbook","Times New Roman",Times,serif;color:#383733;font-size:small;}
|
||||
.articleInfo{color:#474537;font-family:Arial,Helvetica,sans-serif; font-size:xx-small;}
|
||||
.authorName{color:#B61900;font-family:Arial,Helvetica,sans-serif;font-size:medium;}
|
||||
.authorInfo{color:#0066CC;font-family:Arial,Helvetica,sans-serif;font-size:xx-small;}
|
||||
.articleUpdated{ font-size:xx-small; color:#73726C; font-family:Arial,Helvetica,sans-serif;}
|
||||
.issueDate{font-family :Arial,Helvetica,sans-serif;font-size:xx-small;font-style:italic;}
|
||||
.story{color:#333333; font-family:Georgia,"Century Schoolbook","Times New Roman",Times,serif;font-size:small;}
|
||||
.photoCredit{color:#999999;font-family:Arial,Helvetica,sans-serif;font-size:xx-small;}
|
||||
.photoCaption{color:#0A0A09;font-family:Arial,Helvetica,sans-serif;font-size:xx-small;font-weight:bold;}'''
|
||||
|
||||
encoding = 'utf-8'
|
||||
language = _('English')
|
||||
remove_tags = [
|
||||
{'class':['navbar', 'ad', 'sponsorLinksArticle', 'mm-content',
|
||||
{'class':['fwArticle noHr','fwArticle','subinfo','hdlBulletItem','head-content','navbar','link', 'ad', 'sponsorLinksArticle', 'mm-content',
|
||||
'inline-social-links-wrapper', 'email-article',
|
||||
'comments-and-social-links-wrapper', 'EmailArticleBlock']},
|
||||
{'id' : ['footer', 'ticker-data', 'topTenVertical',
|
||||
@ -24,8 +37,6 @@ class Newsweek(BasicNewsRecipe):
|
||||
{'class': re.compile('related-cloud')},
|
||||
]
|
||||
keep_only_tags = [{'class':['article HorizontalHeader', 'articlecontent']}]
|
||||
|
||||
|
||||
recursions = 1
|
||||
match_regexps = [r'http://www.newsweek.com/id/\S+/page/\d+']
|
||||
|
||||
|
@ -16,7 +16,7 @@ class NYTimes(BasicNewsRecipe):
|
||||
__author__ = 'Kovid Goyal'
|
||||
language = _('English')
|
||||
description = 'Daily news from the New York Times (subscription version)'
|
||||
timefmt = ' [%a, %d %b, %Y]'
|
||||
timefmt = ''
|
||||
needs_subscription = True
|
||||
remove_tags_before = dict(id='article')
|
||||
remove_tags_after = dict(id='article')
|
||||
@ -46,39 +46,61 @@ class NYTimes(BasicNewsRecipe):
|
||||
articles = {}
|
||||
key = None
|
||||
ans = []
|
||||
allSectionKeywords = ['The Front Page', 'International','National','Obituaries','Editorials',
|
||||
'New York','Business Day','Sports','Dining','Arts','Home','Styles']
|
||||
excludeSectionKeywords = ['Dining','Styles']
|
||||
|
||||
|
||||
# Find each instance of class="section-headline", class="story", class="story headline"
|
||||
for div in soup.findAll(True,
|
||||
attrs={'class':['section-headline', 'story', 'story headline']}):
|
||||
|
||||
if div['class'] == 'section-headline':
|
||||
key = string.capwords(feed_title(div))
|
||||
excluded = re.compile('|'.join(excludeSectionKeywords))
|
||||
if excluded.search(key):
|
||||
self.log("Skipping section %s" % key)
|
||||
continue
|
||||
|
||||
articles[key] = []
|
||||
ans.append(key)
|
||||
|
||||
elif div['class'] in ['story', 'story headline']:
|
||||
elif div['class'] in ['story', 'story headline'] :
|
||||
a = div.find('a', href=True)
|
||||
if not a:
|
||||
continue
|
||||
url = re.sub(r'\?.*', '', a['href'])
|
||||
url += '?pagewanted=all'
|
||||
title = self.tag_to_string(a, use_alt=True).strip()
|
||||
|
||||
description = ''
|
||||
pubdate = strftime('%a, %d %b')
|
||||
summary = div.find(True, attrs={'class':'summary'})
|
||||
if summary:
|
||||
description = self.tag_to_string(summary, use_alt=False)
|
||||
|
||||
author = ''
|
||||
authorAttribution = div.find(True, attrs={'class':'storyheadline-author'})
|
||||
if authorAttribution:
|
||||
author = self.tag_to_string(authorAttribution, use_alt=False)
|
||||
else:
|
||||
authorAttribution = div.find(True, attrs={'class':'byline'})
|
||||
if authorAttribution:
|
||||
author = self.tag_to_string(authorAttribution, use_alt=False)
|
||||
|
||||
feed = key if key is not None else 'Uncategorized'
|
||||
if not articles.has_key(feed):
|
||||
articles[feed] = []
|
||||
if not 'podcasts' in url:
|
||||
articles[feed].append(
|
||||
dict(title=title, url=url, date=pubdate,
|
||||
description=description,
|
||||
description=description, author=author,
|
||||
content=''))
|
||||
ans = self.sort_index_by(ans, {'The Front Page':-1,
|
||||
'Dining In, Dining Out':1,
|
||||
'Obituaries':2})
|
||||
ans = [(key, articles[key]) for key in ans if articles.has_key(key)]
|
||||
|
||||
return ans
|
||||
|
||||
def preprocess_html(self, soup):
|
||||
|
Loading…
x
Reference in New Issue
Block a user