diff --git a/src/calibre/web/feeds/__init__.py b/src/calibre/web/feeds/__init__.py index 7e1dee577d..3bc1110db9 100644 --- a/src/calibre/web/feeds/__init__.py +++ b/src/calibre/web/feeds/__init__.py @@ -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]) diff --git a/src/calibre/web/feeds/news.py b/src/calibre/web/feeds/news.py index 1bc1fc77d8..7b86263bc7 100644 --- a/src/calibre/web/feeds/news.py +++ b/src/calibre/web/feeds/news.py @@ -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'''\ + + + + + +

%(title)s

+

+
+
+ calibre +
+
+

%(date)s

+




+

%(author)s

+








+

Produced by %(app)s

+
+
+ + + '''%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 @@ -778,7 +867,11 @@ 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) + 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) diff --git a/src/calibre/web/feeds/templates.py b/src/calibre/web/feeds/templates.py index 4cc79a8b89..b2b96bd9a4 100644 --- a/src/calibre/web/feeds/templates.py +++ b/src/calibre/web/feeds/templates.py @@ -145,7 +145,7 @@ class FeedTemplate(Template): ${article.title} ${article.localtime.strftime(" [%a, %d %b %H:%M]")}
- ${Markup(cutoff(article.summary))} + ${Markup(cutoff(article.text_summary))}