diff --git a/recipes/borse_online.recipe b/recipes/borse_online.recipe index c192ce2b8d..ddd9ac456b 100644 --- a/recipes/borse_online.recipe +++ b/recipes/borse_online.recipe @@ -1,33 +1,36 @@ from calibre.web.feeds.recipes import BasicNewsRecipe class AdvancedUserRecipe1303841067(BasicNewsRecipe): - title = u'Börse-online' - __author__ = 'schuster' - oldest_article = 1 + title = u'Börse-online' + __author__ = 'schuster, Armin Geller' + oldest_article = 1 max_articles_per_feed = 100 - no_stylesheets = True - use_embedded_content = False - language = 'de' - remove_javascript = True - cover_url = 'http://www.dpv.de/images/1995/source.gif' - masthead_url = 'http://www.zeitschriften-cover.de/cover/boerse-online-cover-januar-2010-x1387.jpg' - extra_css = ''' - h1{font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:large;} - h4{font-family:Arial,Helvetica,sans-serif; font-weight:normal;font-size:small;} - img {min-width:300px; max-width:600px; min-height:300px; max-height:800px} - p{font-family:Arial,Helvetica,sans-serif;font-size:small;} - body{font-family:Helvetica,Arial,sans-serif;font-size:small;} - ''' - remove_tags_bevor = [dict(name='h3')] - remove_tags_after = [dict(name='div', attrs={'class':'artikelfuss'})] - remove_tags = [dict(attrs={'class':['moduleTopNav', 'moduleHeaderNav', 'text', 'blau', 'poll1150']}), - dict(id=['newsletterlayer', 'newsletterlayerClose', 'newsletterlayer_body', 'newsletterarray_error', 'newsletterlayer_emailadress', 'newsletterlayer_submit', 'kommentar']), - dict(name=['h2', 'Gesamtranking', 'h3',''])] + no_stylesheets = True + use_embedded_content = False + language = 'de' + remove_javascript = True + encoding = 'iso-8859-1' + timefmt = ' [%a, %d %b %Y]' + + + cover_url = 'http://www.wirtschaftsmedien-shop.de/s/media/coverimages/7576_2013107.jpg' + masthead_url = 'http://upload.wikimedia.org/wikipedia/de/5/56/B%C3%B6rse_Online_Logo.svg' + remove_tags_after = [dict(name='div', attrs={'class':['artikelfuss', 'rahmen600']})] + + remove_tags = [ + dict(name='div', attrs={'id':['breadcrumb', 'rightCol', 'clearall']}), + dict(name='div', attrs={'class':['footer', 'artikelfuss']}), + ] + + keep_only_tags = [ + dict(name='div', attrs={'id':['contentWrapper']}) + ] + + feeds = [(u'Börsennachrichten', u'http://www.boerse-online.de/rss/')] + def print_version(self, url): return url.replace('.html#nv=rss', '.html?mode=print') - feeds = [(u'Börsennachrichten', u'http://www.boerse-online.de/rss/')] - diff --git a/recipes/icons/libartes.png b/recipes/icons/libartes.png new file mode 100644 index 0000000000..0954c40273 Binary files /dev/null and b/recipes/icons/libartes.png differ diff --git a/recipes/libartes.recipe b/recipes/libartes.recipe new file mode 100644 index 0000000000..6ddae87119 --- /dev/null +++ b/recipes/libartes.recipe @@ -0,0 +1,69 @@ +__license__ = 'GPL v3' +__copyright__ = '2013, Darko Miletic ' +''' +libartes.com +''' + +import re +from calibre import strftime +from calibre.web.feeds.news import BasicNewsRecipe + +class Libartes(BasicNewsRecipe): + title = 'Libartes' + __author__ = 'Darko Miletic' + description = 'Elektronski časopis Libartes delo je kulturnih entuzijasta, umetnika i teoretičara umetnosti i književnosti. Časopis Libartes izlazi tromesečno i bavi se različitim granama umetnosti - književnošću, muzikom, filmom, likovnim umetnostima, dizajnom i arhitekturom.' + publisher = 'Libartes' + category = 'literatura, knjizevnost, film, dizajn, arhitektura, muzika' + no_stylesheets = True + INDEX = 'http://libartes.com/' + use_embedded_content = False + encoding = 'utf-8' + language = 'sr' + publication_type = 'magazine' + masthead_url = 'http://libartes.com/index_files/logo.gif' + extra_css = """ + @font-face {font-family: "serif1";src:url(res:///opt/sony/ebook/FONT/tt0011m_.ttf)} + @font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)} + body{font-family: "Times New Roman",Times,serif1, serif} + img{display:block} + .naslov{font-size: xx-large; font-weight: bold} + .nag{font-size: large; font-weight: bold} + """ + + conversion_options = { + 'comment' : description + , 'tags' : category + , 'publisher' : publisher + , 'language' : language + } + + + preprocess_regexps = [(re.compile(u'\u0110'), lambda match: u'\u00D0')] + remove_tags_before = dict(attrs={'id':'nav'}) + remove_tags_after = dict(attrs={'id':'fb' }) + keep_only_tags = [dict(name='div', attrs={'id':'center_content'})] + remove_tags = [ + dict(name=['object','link','iframe','embed','meta']) + ,dict(attrs={'id':'nav'}) + ] + + def parse_index(self): + articles = [] + soup = self.index_to_soup(self.INDEX) + for item in soup.findAll(name='a', attrs={'class':'belad'}, href=True): + feed_link = item + if feed_link['href'].startswith(self.INDEX): + url = feed_link['href'] + else: + url = self.INDEX + feed_link['href'] + + title = self.tag_to_string(feed_link) + date = strftime(self.timefmt) + articles.append({ + 'title' :title + ,'date' :date + ,'url' :url + ,'description':'' + }) + return [('Casopis Libartes', articles)] + diff --git a/src/calibre/ebooks/conversion/plugins/pdf_output.py b/src/calibre/ebooks/conversion/plugins/pdf_output.py index e4eb45fc6a..b9d016de2d 100644 --- a/src/calibre/ebooks/conversion/plugins/pdf_output.py +++ b/src/calibre/ebooks/conversion/plugins/pdf_output.py @@ -10,7 +10,7 @@ Convert OEB ebook format to PDF. import glob, os -from calibre.constants import iswindows +from calibre.constants import iswindows, islinux from calibre.customize.conversion import (OutputFormatPlugin, OptionRecommendation) from calibre.ptempfile import TemporaryDirectory @@ -73,13 +73,13 @@ class PDFOutput(OutputFormatPlugin): ' of stretching it to fill the full first page of the' ' generated pdf.')), OptionRecommendation(name='pdf_serif_family', - recommended_value='Times New Roman', help=_( + recommended_value='Liberation Serif' if islinux else 'Times New Roman', help=_( 'The font family used to render serif fonts')), OptionRecommendation(name='pdf_sans_family', - recommended_value='Helvetica', help=_( + recommended_value='Liberation Sans' if islinux else 'Helvetica', help=_( 'The font family used to render sans-serif fonts')), OptionRecommendation(name='pdf_mono_family', - recommended_value='Courier New', help=_( + recommended_value='Liberation Mono' if islinux else 'Courier New', help=_( 'The font family used to render monospaced fonts')), OptionRecommendation(name='pdf_standard_font', choices=['serif', 'sans', 'mono'], @@ -102,6 +102,10 @@ class PDFOutput(OutputFormatPlugin): ]) def convert(self, oeb_book, output_path, input_plugin, opts, log): + from calibre.gui2 import must_use_qt, load_builtin_fonts + must_use_qt() + load_builtin_fonts() + self.oeb = oeb_book self.input_plugin, self.opts, self.log = input_plugin, opts, log self.output_path = output_path @@ -135,7 +139,6 @@ class PDFOutput(OutputFormatPlugin): If you ever move to Qt WebKit 2.3+ then this will be unnecessary. ''' from calibre.ebooks.oeb.base import urlnormalize - from calibre.gui2 import must_use_qt from calibre.utils.fonts.utils import remove_embed_restriction from PyQt4.Qt import QFontDatabase, QByteArray, QRawFont, QFont @@ -165,7 +168,6 @@ class PDFOutput(OutputFormatPlugin): raw = remove_embed_restriction(raw) except: continue - must_use_qt() fid = QFontDatabase.addApplicationFontFromData(QByteArray(raw)) family_name = None if fid > -1: diff --git a/src/calibre/ebooks/pdf/render/engine.py b/src/calibre/ebooks/pdf/render/engine.py index 149d75d1f0..a987b3a54d 100644 --- a/src/calibre/ebooks/pdf/render/engine.py +++ b/src/calibre/ebooks/pdf/render/engine.py @@ -239,7 +239,7 @@ class PdfEngine(QPaintEngine): @store_error def drawTextItem(self, point, text_item): - # super(PdfEngine, self).drawTextItem(point, text_item) + # return super(PdfEngine, self).drawTextItem(point, text_item) self.apply_graphics_state() gi = self.qt_hack.get_glyphs(point, text_item) if not gi.indices: @@ -247,7 +247,10 @@ class PdfEngine(QPaintEngine): return name = hash(bytes(gi.name)) if name not in self.fonts: - self.fonts[name] = self.create_sfnt(text_item) + try: + self.fonts[name] = self.create_sfnt(text_item) + except UnsupportedFont: + return super(PdfEngine, self).drawTextItem(point, text_item) metrics = self.fonts[name] for glyph_id in gi.indices: try: diff --git a/src/calibre/ebooks/pdf/render/from_html.py b/src/calibre/ebooks/pdf/render/from_html.py index edf5db1882..191da98893 100644 --- a/src/calibre/ebooks/pdf/render/from_html.py +++ b/src/calibre/ebooks/pdf/render/from_html.py @@ -147,9 +147,10 @@ class PDFWriter(QObject): opts = self.opts page_size = get_page_size(self.opts) xdpi, ydpi = self.view.logicalDpiX(), self.view.logicalDpiY() + # We cannot set the side margins in the webview as there is no right + # margin for the last page (the margins are implemented with + # -webkit-column-gap) ml, mr = opts.margin_left, opts.margin_right - margin_side = min(ml, mr) - ml, mr = ml - margin_side, mr - margin_side self.doc = PdfDevice(out_stream, page_size=page_size, left_margin=ml, top_margin=0, right_margin=mr, bottom_margin=0, xdpi=xdpi, ydpi=ydpi, errors=self.log.error, @@ -162,9 +163,7 @@ class PDFWriter(QObject): self.total_items = len(items) mt, mb = map(self.doc.to_px, (opts.margin_top, opts.margin_bottom)) - ms = self.doc.to_px(margin_side, vertical=False) - self.margin_top, self.margin_size, self.margin_bottom = map( - lambda x:int(floor(x)), (mt, ms, mb)) + self.margin_top, self.margin_bottom = map(lambda x:int(floor(x)), (mt, mb)) self.painter = QPainter(self.doc) self.doc.set_metadata(title=pdf_metadata.title, @@ -185,7 +184,8 @@ class PDFWriter(QObject): self.painter.restore() QTimer.singleShot(0, self.render_book) - self.loop.exec_() + if self.loop.exec_() == 1: + raise Exception('PDF Output failed, see log for details') if self.toc is not None and len(self.toc) > 0: self.doc.add_outline(self.toc) @@ -258,7 +258,7 @@ class PDFWriter(QObject): paged_display.layout(); paged_display.fit_images(); py_bridge.value = book_indexing.all_links_and_anchors(); - '''%(self.margin_top, self.margin_size, self.margin_bottom)) + '''%(self.margin_top, 0, self.margin_bottom)) amap = self.bridge_value if not isinstance(amap, dict): diff --git a/src/calibre/ebooks/pdf/render/graphics.py b/src/calibre/ebooks/pdf/render/graphics.py index 71a8a22e85..7fb87662b4 100644 --- a/src/calibre/ebooks/pdf/render/graphics.py +++ b/src/calibre/ebooks/pdf/render/graphics.py @@ -11,7 +11,7 @@ from math import sqrt from collections import namedtuple from PyQt4.Qt import ( - QBrush, QPen, Qt, QPointF, QTransform, QPainterPath, QPaintEngine, QImage) + QBrush, QPen, Qt, QPointF, QTransform, QPaintEngine, QImage) from calibre.ebooks.pdf.render.common import ( Name, Array, fmtnum, Stream, Dictionary) @@ -248,7 +248,7 @@ class TexturePattern(TilingPattern): class GraphicsState(object): FIELDS = ('fill', 'stroke', 'opacity', 'transform', 'brush_origin', - 'clip', 'do_fill', 'do_stroke') + 'clip_updated', 'do_fill', 'do_stroke') def __init__(self): self.fill = QBrush() @@ -256,7 +256,7 @@ class GraphicsState(object): self.opacity = 1.0 self.transform = QTransform() self.brush_origin = QPointF() - self.clip = QPainterPath() + self.clip_updated = False self.do_fill = False self.do_stroke = True self.qt_pattern_cache = {} @@ -274,7 +274,7 @@ class GraphicsState(object): ans.opacity = self.opacity ans.transform = self.transform * QTransform() ans.brush_origin = QPointF(self.brush_origin) - ans.clip = self.clip + ans.clip_updated = self.clip_updated ans.do_fill, ans.do_stroke = self.do_fill, self.do_stroke return ans @@ -311,7 +311,7 @@ class Graphics(object): s.opacity = state.opacity() if flags & QPaintEngine.DirtyClipPath or flags & QPaintEngine.DirtyClipRegion: - s.clip = painter.clipPath() + s.clip_updated = True def reset(self): self.current_state = GraphicsState() @@ -326,7 +326,7 @@ class Graphics(object): ps = self.pending_state pdf = self.pdf - if (ps.transform != pdf_state.transform or ps.clip != pdf_state.clip): + if ps.transform != pdf_state.transform or ps.clip_updated: pdf.restore_stack() pdf.save_stack() pdf_state = self.base_state @@ -341,11 +341,14 @@ class Graphics(object): pdf_state.brush_origin != ps.brush_origin): self.apply_fill(ps, pdf_system, painter) - if (pdf_state.clip != ps.clip): - p = convert_path(ps.clip) - fill_rule = {Qt.OddEvenFill:'evenodd', - Qt.WindingFill:'winding'}[ps.clip.fillRule()] - pdf.add_clip(p, fill_rule=fill_rule) + if ps.clip_updated: + ps.clip_updated = False + path = painter.clipPath() + if not path.isEmpty(): + p = convert_path(path) + fill_rule = {Qt.OddEvenFill:'evenodd', + Qt.WindingFill:'winding'}[path.fillRule()] + pdf.add_clip(p, fill_rule=fill_rule) self.current_state = self.pending_state self.pending_state = None diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 9dbf769511..d7a2669b0b 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -766,6 +766,26 @@ class Translator(QTranslator): gui_thread = None qt_app = None + +def load_builtin_fonts(): + global _rating_font + # Load the builtin fonts and any fonts added to calibre by the user to + # Qt + for ff in glob.glob(P('fonts/liberation/*.?tf')) + \ + [P('fonts/calibreSymbols.otf')] + \ + glob.glob(os.path.join(config_dir, 'fonts', '*.?tf')): + if ff.rpartition('.')[-1].lower() in {'ttf', 'otf'}: + with open(ff, 'rb') as s: + # Windows requires font files to be executable for them to be + # loaded successfully, so we use the in memory loader + fid = QFontDatabase.addApplicationFontFromData(s.read()) + if fid > -1: + fam = QFontDatabase.applicationFontFamilies(fid) + fam = set(map(unicode, fam)) + if u'calibre Symbols' in fam: + _rating_font = u'calibre Symbols' + + class Application(QApplication): def __init__(self, args, force_calibre_style=False, @@ -798,27 +818,12 @@ class Application(QApplication): return ret def load_builtin_fonts(self, scan_for_fonts=False): - global _rating_font if scan_for_fonts: from calibre.utils.fonts.scanner import font_scanner # Start scanning the users computer for fonts font_scanner - # Load the builtin fonts and any fonts added to calibre by the user to - # Qt - for ff in glob.glob(P('fonts/liberation/*.?tf')) + \ - [P('fonts/calibreSymbols.otf')] + \ - glob.glob(os.path.join(config_dir, 'fonts', '*.?tf')): - if ff.rpartition('.')[-1].lower() in {'ttf', 'otf'}: - with open(ff, 'rb') as s: - # Windows requires font files to be executable for them to be - # loaded successfully, so we use the in memory loader - fid = QFontDatabase.addApplicationFontFromData(s.read()) - if fid > -1: - fam = QFontDatabase.applicationFontFamilies(fid) - fam = set(map(unicode, fam)) - if u'calibre Symbols' in fam: - _rating_font = u'calibre Symbols' + load_builtin_fonts() def load_calibre_style(self): # On OS X QtCurve resets the palette, so we preserve it explicitly diff --git a/src/calibre/gui2/dialogs/metadata_bulk.ui b/src/calibre/gui2/dialogs/metadata_bulk.ui index 917dfbb159..24a84eb1b4 100644 --- a/src/calibre/gui2/dialogs/metadata_bulk.ui +++ b/src/calibre/gui2/dialogs/metadata_bulk.ui @@ -1109,8 +1109,8 @@ not multiple and the destination field is multiple 0 0 - 205 - 66 + 934 + 213 @@ -1269,8 +1269,8 @@ not multiple and the destination field is multiple accept() - 252 - 382 + 258 + 638 157 @@ -1285,8 +1285,8 @@ not multiple and the destination field is multiple reject() - 320 - 382 + 326 + 638 286 @@ -1294,5 +1294,37 @@ not multiple and the destination field is multiple + + remove_all_tags + toggled(bool) + remove_tags + setDisabled(bool) + + + 888 + 266 + + + 814 + 268 + + + + + clear_languages + toggled(bool) + languages + setDisabled(bool) + + + 874 + 418 + + + 817 + 420 + + +