Fix regression in windows that was causing downloaded news to not have a cover

This commit is contained in:
Kovid Goyal 2009-04-02 15:18:29 -07:00
parent 62688a6822
commit f7195f81aa
2 changed files with 78 additions and 44 deletions

View File

@ -6,6 +6,9 @@ Code for the conversion of ebook formats and the reading of metadata
from various formats. from various formats.
''' '''
import traceback, os
from calibre import CurrentDir
class ConversionError(Exception): class ConversionError(Exception):
def __init__(self, msg, only_msg=False): def __init__(self, msg, only_msg=False):
@ -22,3 +25,54 @@ BOOK_EXTENSIONS = ['lrf', 'rar', 'zip', 'rtf', 'lit', 'txt', 'htm', 'xhtm',
'html', 'xhtml', 'pdf', 'prc', 'mobi', 'azw', 'html', 'xhtml', 'pdf', 'prc', 'mobi', 'azw',
'epub', 'fb2', 'djvu', 'lrx', 'cbr', 'cbz', 'oebzip', 'epub', 'fb2', 'djvu', 'lrx', 'cbr', 'cbz', 'oebzip',
'rb', 'imp', 'odt'] 'rb', 'imp', 'odt']
class HTMLRenderer(object):
def __init__(self, page, loop):
self.page, self.loop = page, loop
self.data = ''
self.exception = self.tb = None
def __call__(self, ok):
from PyQt4.Qt import QImage, QPainter, QByteArray, QBuffer
try:
if not ok:
raise RuntimeError('Rendering of HTML failed.')
image = QImage(self.page.viewportSize(), QImage.Format_ARGB32)
image.setDotsPerMeterX(96*(100/2.54))
image.setDotsPerMeterY(96*(100/2.54))
painter = QPainter(image)
self.page.mainFrame().render(painter)
painter.end()
ba = QByteArray()
buf = QBuffer(ba)
buf.open(QBuffer.WriteOnly)
image.save(buf, 'JPEG')
self.data = str(ba.data())
except Exception, e:
self.exception = e
self.traceback = traceback.format_exc()
finally:
self.loop.exit(0)
def render_html(path_to_html, width=590, height=750):
from PyQt4.QtWebKit import QWebPage
from PyQt4.Qt import QEventLoop, QPalette, Qt, SIGNAL, QUrl, QSize
path_to_html = os.path.abspath(path_to_html)
with CurrentDir(os.path.dirname(path_to_html)):
page = QWebPage()
pal = page.palette()
pal.setBrush(QPalette.Background, Qt.white)
page.setPalette(pal)
page.setViewportSize(QSize(width, height))
page.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)
page.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
loop = QEventLoop()
renderer = HTMLRenderer(page, loop)
page.connect(page, SIGNAL('loadFinished(bool)'), renderer)
page.mainFrame().load(QUrl.fromLocalFile(path_to_html))
loop.exec_()
return renderer

View File

@ -7,14 +7,12 @@ Defines various abstract base classes that can be subclassed to create powerful
__docformat__ = "restructuredtext en" __docformat__ = "restructuredtext en"
import logging, os, cStringIO, time, traceback, re, urlparse, sys, tempfile, functools import logging, os, cStringIO, time, traceback, re, urlparse, sys
from collections import defaultdict from collections import defaultdict
from functools import partial from functools import partial
from contextlib import nested, closing from contextlib import nested, closing
from PyQt4.Qt import QApplication, QFile, Qt, QPalette, QSize, QImage, QPainter, \ from PyQt4.Qt import QApplication, QFile, QIODevice
QBuffer, QByteArray, SIGNAL, QUrl, QEventLoop, QIODevice
from PyQt4.QtWebKit import QWebPage
from calibre import browser, __appname__, iswindows, LoggingInterface, \ from calibre import browser, __appname__, iswindows, LoggingInterface, \
@ -22,14 +20,15 @@ from calibre import browser, __appname__, iswindows, LoggingInterface, \
from calibre.ebooks.BeautifulSoup import BeautifulSoup, NavigableString, CData, Tag from calibre.ebooks.BeautifulSoup import BeautifulSoup, NavigableString, CData, Tag
from calibre.ebooks.metadata.opf2 import OPFCreator from calibre.ebooks.metadata.opf2 import OPFCreator
from calibre.ebooks.lrf import entity_to_unicode from calibre.ebooks.lrf import entity_to_unicode
from calibre.ebooks import render_html
from calibre.ebooks.metadata.toc import TOC from calibre.ebooks.metadata.toc import TOC
from calibre.ebooks.metadata import MetaInformation from calibre.ebooks.metadata import MetaInformation
from calibre.web.feeds import feed_from_xml, templates, feeds_from_index, Feed from calibre.web.feeds import feed_from_xml, templates, feeds_from_index, Feed
from calibre.web.fetch.simple import option_parser as web2disk_option_parser from calibre.web.fetch.simple import option_parser as web2disk_option_parser
from calibre.web.fetch.simple import RecursiveFetcher from calibre.web.fetch.simple import RecursiveFetcher
from calibre.utils.threadpool import WorkRequest, ThreadPool, NoResultsPending from calibre.utils.threadpool import WorkRequest, ThreadPool, NoResultsPending
from calibre.ptempfile import PersistentTemporaryFile from calibre.ptempfile import PersistentTemporaryFile, \
from calibre.gui2 import images_rc # Needed for default cover PersistentTemporaryDirectory
class BasicNewsRecipe(object, LoggingInterface): class BasicNewsRecipe(object, LoggingInterface):
@ -788,15 +787,18 @@ class BasicNewsRecipe(object, LoggingInterface):
''' '''
Create a generic cover for recipes that dont have a cover Create a generic cover for recipes that dont have a cover
''' '''
from calibre.gui2 import images_rc # Needed for access to logo
images_rc
if QApplication.instance() is None: QApplication([]) if QApplication.instance() is None: QApplication([])
f = QFile(':/library') f = QFile(':/library')
f.open(QIODevice.ReadOnly) f.open(QIODevice.ReadOnly)
img = str(f.readAll()) img_data = str(f.readAll())
tdir = PersistentTemporaryDirectory('_default_cover')
img = os.path.join(tdir, 'logo.png')
with open(img, 'wb') as g:
g.write(img_data)
f.close() f.close()
f = tempfile.NamedTemporaryFile(suffix='library.png') img = os.path.basename(img)
f.write(img)
f.flush()
img = f.name
html= u'''\ html= u'''\
<html> <html>
<head> <head>
@ -835,38 +837,16 @@ class BasicNewsRecipe(object, LoggingInterface):
date=strftime(self.timefmt), date=strftime(self.timefmt),
app=__appname__ +' '+__version__, app=__appname__ +' '+__version__,
img=img) img=img)
f2 = tempfile.NamedTemporaryFile(suffix='cover.html') hf = os.path.join(tdir, 'cover.htm')
f2.write(html.encode('utf-8')) with open(hf, 'wb') as f:
f2.flush() f.write(html.encode('utf-8'))
page = QWebPage() renderer = render_html(hf)
pal = page.palette() if renderer.tb is not None:
pal.setBrush(QPalette.Background, Qt.white) self.logger.warning('Failed to render default cover')
page.setPalette(pal) self.logger.debug(renderer.tb)
page.setViewportSize(QSize(590, 750)) else:
page.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) cover_file.write(renderer.data)
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() 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): def create_opf(self, feeds, dir=None):