mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 10:14:46 -04:00
Pull from trunk
This commit is contained in:
commit
ca0fb160f2
@ -2,7 +2,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
__appname__ = 'calibre'
|
__appname__ = 'calibre'
|
||||||
__version__ = '0.5.4'
|
__version__ = '0.5.5'
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
'''
|
'''
|
||||||
Various run time constants.
|
Various run time constants.
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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, \
|
from calibre import browser, __appname__, iswindows, \
|
||||||
@ -22,14 +20,15 @@ from calibre import browser, __appname__, iswindows, \
|
|||||||
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):
|
class BasicNewsRecipe(object):
|
||||||
@ -787,15 +786,18 @@ class BasicNewsRecipe(object):
|
|||||||
'''
|
'''
|
||||||
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>
|
||||||
@ -834,38 +836,16 @@ class BasicNewsRecipe(object):
|
|||||||
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):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user