Create a generic cover for news recipes that dont specify one

This commit is contained in:
Kovid Goyal 2008-12-09 18:10:41 -08:00
parent b6df865ffd
commit ec1b12b494
3 changed files with 99 additions and 5 deletions

View File

@ -20,6 +20,7 @@ class Article(object):
self.id = id
self.title = title.strip() if title else title
self.url = url
self.summary = summary
if summary and not isinstance(summary, unicode):
summary = summary.decode('utf-8', 'replace')
if summary and '<' in summary:
@ -31,7 +32,7 @@ class Article(object):
print summary.encode('utf-8')
traceback.print_exc()
summary = u''
self.summary = summary
self.text_summary = summary
self.content = content
self.date = published
self.utctime = datetime(*self.date[:6])

View File

@ -7,12 +7,17 @@ Defines various abstract base classes that can be subclassed to create powerful
__docformat__ = "restructuredtext en"
import logging, os, cStringIO, time, traceback, re, urlparse, sys
import logging, os, cStringIO, time, traceback, re, urlparse, sys, tempfile, functools
from collections import defaultdict
from functools import partial
from contextlib import nested, closing
from calibre import browser, __appname__, iswindows, LoggingInterface, strftime
from PyQt4.Qt import QApplication, QFile, Qt, QPalette, QSize, QImage, QPainter, \
QBuffer, QByteArray, SIGNAL, QUrl, QEventLoop, QIODevice
from PyQt4.QtWebKit import QWebPage
from calibre import browser, __appname__, iswindows, LoggingInterface, strftime, __version__
from calibre.ebooks.BeautifulSoup import BeautifulSoup, NavigableString, CData, Tag
from calibre.ebooks.metadata.opf import OPFCreator
from calibre.ebooks.lrf import entity_to_unicode
@ -23,6 +28,7 @@ from calibre.web.fetch.simple import option_parser as web2disk_option_parser
from calibre.web.fetch.simple import RecursiveFetcher
from calibre.utils.threadpool import WorkRequest, ThreadPool, NoResultsPending
from calibre.ptempfile import PersistentTemporaryFile
from calibre.gui2 import images_rc # Needed for default cover
class BasicNewsRecipe(object, LoggingInterface):
@ -766,6 +772,89 @@ class BasicNewsRecipe(object, LoggingInterface):
self.cover_path = cpath
def default_cover(self, cover_file):
'''
Create a generic cover for recipes that dont have a cover
'''
if QApplication.instance() is None: QApplication([])
f = QFile(':/library')
f.open(QIODevice.ReadOnly)
img = str(f.readAll())
f.close()
f = tempfile.NamedTemporaryFile(suffix='library.png')
f.write(img)
f.flush()
img = f.name
html= u'''\
<html>
<head>
<style type="text/css">
body {
background: white no-repeat fixed center center;
text-align: center;
vertical-align: center;
overflow: hidden;
font-size: 18px;
}
h1 { font-family: serif; }
h2, h4 { font-family: monospace; }
</style>
</head>
<body>
<h1>%(title)s</h1>
<br/><br/>
<div style="position:relative">
<div style="position: absolute; left: 0; top: 0; width:100%%; height:100%%; vertical-align:center">
<img src="%(img)s" alt="calibre" style="opacity:0.3"/>
</div>
<div style="position: absolute; left: 0; top: 0; width:100%%; height:100%%; vertical-align:center">
<h2>%(date)s</h2>
<br/><br/><br/><br/><br/>
<h3>%(author)s</h3>
<br/><br/></br/><br/><br/><br/><br/><br/><br/>
<h4>Produced by %(app)s</h4>
</div>
</div>
</body>
</html>
'''%dict(title=self.title, author=self.__author__,
date=time.strftime(self.timefmt),
app=__appname__ +' '+__version__,
img=img)
f2 = tempfile.NamedTemporaryFile(suffix='cover.html')
f2.write(html)
f2.flush()
page = QWebPage()
pal = page.palette()
pal.setBrush(QPalette.Background, Qt.white)
page.setPalette(pal)
page.setViewportSize(QSize(590, 750))
page.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)
page.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
loop = QEventLoop()
def render_html(page, loop, ok):
try:
image = QImage(page.viewportSize(), QImage.Format_ARGB32)
image.setDotsPerMeterX(96*(100/2.54))
image.setDotsPerMeterY(96*(100/2.54))
painter = QPainter(image)
page.mainFrame().render(painter)
painter.end()
ba = QByteArray()
buf = QBuffer(ba)
buf.open(QBuffer.WriteOnly)
image.save(buf, 'JPEG')
image_data = str(ba.data())
cover_file.write(image_data)
cover_file.flush()
finally:
loop.exit(0)
page.connect(page, SIGNAL('loadFinished(bool)'), functools.partial(render_html, page, loop))
page.mainFrame().load(QUrl.fromLocalFile(f2.name))
loop.exec_()
def create_opf(self, feeds, dir=None):
if dir is None:
dir = self.output_dir
@ -779,6 +868,10 @@ class BasicNewsRecipe(object, LoggingInterface):
manifest = [os.path.join(dir, 'feed_%d'%i) for i in range(len(feeds))]
manifest.append(os.path.join(dir, 'index.html'))
cpath = getattr(self, 'cover_path', None)
if cpath is None:
pf = PersistentTemporaryFile('_recipe_cover.jpg')
self.default_cover(pf)
cpath = pf.name
if cpath is not None and os.access(cpath, os.R_OK):
opf.cover = cpath
manifest.append(cpath)

View File

@ -145,7 +145,7 @@ class FeedTemplate(Template):
<a class="article" href="${article.url}">${article.title}</a>
<span class="article_date">${article.localtime.strftime(" [%a, %d %b %H:%M]")}</span>
<div class="article_decription" py:if="article.summary">
${Markup(cutoff(article.summary))}
${Markup(cutoff(article.text_summary))}
</div>
</li>
</py:for>