From 30050f00334c855e9f432f7a0ceb581cd4e5eee2 Mon Sep 17 00:00:00 2001 From: John Schember Date: Sun, 26 Dec 2010 21:35:31 -0500 Subject: [PATCH 01/26] PDF Output: Simplify building printer object. Fix regessions that prevented options such as margins from being honored. --- src/calibre/ebooks/pdf/writer.py | 37 +++++++------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/src/calibre/ebooks/pdf/writer.py b/src/calibre/ebooks/pdf/writer.py index 03519a2cbb..2ae1638a73 100644 --- a/src/calibre/ebooks/pdf/writer.py +++ b/src/calibre/ebooks/pdf/writer.py @@ -25,10 +25,6 @@ from PyQt4.QtWebKit import QWebView from pyPdf import PdfFileWriter, PdfFileReader -def get_pdf_printer(): - return QPrinter(QPrinter.HighResolution) - - def get_custom_size(opts): custom_size = None if opts.custom_size != None: @@ -42,12 +38,12 @@ def get_custom_size(opts): custom_size = None return custom_size -def setup_printer(opts, for_comic=False): +def get_pdf_printer(opts, for_comic=False): from calibre.gui2 import is_ok_to_use_qt if not is_ok_to_use_qt(): raise Exception('Not OK to use Qt') - printer = get_pdf_printer() + printer = QPrinter(QPrinter.HighResolution) custom_size = get_custom_size(opts) if opts.output_profile.short_name == 'default': @@ -63,13 +59,14 @@ def setup_printer(opts, for_comic=False): dpi = opts.output_profile.dpi printer.setPaperSize(QSizeF(float(w) / dpi, float(h)/dpi), QPrinter.Inch) - printer.setPageMargins(0, 0, 0, 0, QPrinter.Point) + printer.setPageMargins(opts.margin_left, opts.margin_top, opts.margin_right, opts.margin_bottom, QPrinter.Point) printer.setOrientation(orientation(opts.orientation)) printer.setOutputFormat(QPrinter.PdfFormat) + printer.setFullPage(True) return printer def get_printer_page_size(opts, for_comic=False): - printer = setup_printer(opts, for_comic=for_comic) + printer = get_pdf_printer(opts, for_comic=for_comic) size = printer.paperSize(QPrinter.Millimeter) return size.width() / 10., size.height() / 10. @@ -154,24 +151,11 @@ class PDFWriter(QObject): # {{{ self.view.load(QUrl.fromLocalFile(item)) - def get_printer(self, set_horz_margins=False): - printer = get_pdf_printer() - printer.setPaperSize(QSizeF(self.size[0] * 10, self.size[1] * 10), QPrinter.Millimeter) - if set_horz_margins: - printer.setPageMargins(0., self.opts.margin_top, 0., - self.opts.margin_bottom, QPrinter.Point) - else: - printer.setPageMargins(0, 0, 0, 0, QPrinter.Point) - printer.setOrientation(orientation(self.opts.orientation)) - printer.setOutputFormat(QPrinter.PdfFormat) - printer.setFullPage(not set_horz_margins) - return printer - def _render_html(self, ok): if ok: item_path = os.path.join(self.tmp_path, '%i.pdf' % len(self.combine_queue)) - self.logger.debug('\tRendering item %s as %i' % (os.path.basename(str(self.view.url().toLocalFile())), len(self.combine_queue))) - printer = self.get_printer(set_horz_margins=True) + self.logger.debug('\tRendering item %s as %i.pdf' % (os.path.basename(str(self.view.url().toLocalFile())), len(self.combine_queue))) + printer = get_pdf_printer(self.opts) printer.setOutputFileName(item_path) self.view.print_(printer) self._render_book() @@ -233,16 +217,11 @@ class ImagePDFWriter(object): os.remove(f.name) def render_images(self, outpath, mi, items): - printer = get_pdf_printer() - printer.setPaperSize(QSizeF(self.size[0] * 10, self.size[1] * 10), QPrinter.Millimeter) - printer.setPageMargins(0, 0, 0, 0, QPrinter.Point) - printer.setOrientation(orientation(self.opts.orientation)) - printer.setOutputFormat(QPrinter.PdfFormat) + printer = get_pdf_printer(self.opts) printer.setOutputFileName(outpath) printer.setDocName(mi.title) printer.setCreator(u'%s [%s]'%(__appname__, __version__)) # Seems to be no way to set author - printer.setFullPage(True) painter = QPainter(printer) painter.setRenderHints(QPainter.Antialiasing|QPainter.SmoothPixmapTransform) From 4e2f5ee60e9d99944cd951838a7a2ba63b157e6c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 27 Dec 2010 00:09:43 -0700 Subject: [PATCH 02/26] Fix specially for the beloved maintainer of poppler --- COPYRIGHT | 5 +++++ src/calibre/ebooks/pdf/fonts.cpp | 2 +- src/calibre/ebooks/pdf/fonts.h | 2 +- src/calibre/ebooks/pdf/images.cpp | 7 +++++++ src/calibre/ebooks/pdf/images.h | 7 +++++++ src/calibre/ebooks/pdf/links.cpp | 2 +- src/calibre/ebooks/pdf/links.h | 2 +- src/calibre/ebooks/pdf/main.cpp | 7 +++++++ src/calibre/ebooks/pdf/reflow.cpp | 2 +- src/calibre/ebooks/pdf/reflow.h | 2 +- src/calibre/ebooks/pdf/utils.h | 2 +- 11 files changed, 33 insertions(+), 7 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index a31d1dbcda..8790fb69dd 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -4,6 +4,11 @@ License: GPL-3 The full text of the GPL is distributed as in /usr/share/common-licenses/GPL-3 on Debian systems. +Files: src/calibre/ebooks/pdf/*.h,*.cpp +License: GPL-2 or later + The full text of the GPL is distributed as in + /usr/share/common-licenses/GPL-2 on Debian systems. + Files: src/calibre/ebooks/BeautifulSoup.py Copyright: Copyright (c) 2004-2007, Leonard Richardson License: BSD diff --git a/src/calibre/ebooks/pdf/fonts.cpp b/src/calibre/ebooks/pdf/fonts.cpp index 3cd7ef0c5b..99ab7517c1 100644 --- a/src/calibre/ebooks/pdf/fonts.cpp +++ b/src/calibre/ebooks/pdf/fonts.cpp @@ -1,6 +1,6 @@ /** * Copyright 2009 Kovid Goyal - * License: GNU GPL v3 + * License: GNU GPL v2+ */ diff --git a/src/calibre/ebooks/pdf/fonts.h b/src/calibre/ebooks/pdf/fonts.h index 55202c9573..1b380e1b87 100644 --- a/src/calibre/ebooks/pdf/fonts.h +++ b/src/calibre/ebooks/pdf/fonts.h @@ -1,6 +1,6 @@ /** * Copyright 2009 Kovid Goyal - * License: GNU GPL v3 + * License: GNU GPL v2+ */ diff --git a/src/calibre/ebooks/pdf/images.cpp b/src/calibre/ebooks/pdf/images.cpp index b3b062e1f4..4cd1ace776 100644 --- a/src/calibre/ebooks/pdf/images.cpp +++ b/src/calibre/ebooks/pdf/images.cpp @@ -1,3 +1,10 @@ +/** + * Copyright 2009 Kovid Goyal + * License: GNU GPL v2+ + */ + + + #include #include #include diff --git a/src/calibre/ebooks/pdf/images.h b/src/calibre/ebooks/pdf/images.h index 7d6f143147..1b4d9b58bf 100644 --- a/src/calibre/ebooks/pdf/images.h +++ b/src/calibre/ebooks/pdf/images.h @@ -1,3 +1,10 @@ +/** + * Copyright 2009 Kovid Goyal + * License: GNU GPL v2+ + */ + + + #pragma once #include diff --git a/src/calibre/ebooks/pdf/links.cpp b/src/calibre/ebooks/pdf/links.cpp index 414ff5ce24..8d28492bab 100644 --- a/src/calibre/ebooks/pdf/links.cpp +++ b/src/calibre/ebooks/pdf/links.cpp @@ -1,6 +1,6 @@ /** * Copyright 2009 Kovid Goyal - * License: GNU GPL v3 + * License: GNU GPL v2+ */ diff --git a/src/calibre/ebooks/pdf/links.h b/src/calibre/ebooks/pdf/links.h index a8a3127a77..c43911ddca 100644 --- a/src/calibre/ebooks/pdf/links.h +++ b/src/calibre/ebooks/pdf/links.h @@ -1,6 +1,6 @@ /** * Copyright 2009 Kovid Goyal - * License: GNU GPL v3 + * License: GNU GPL v2+ */ diff --git a/src/calibre/ebooks/pdf/main.cpp b/src/calibre/ebooks/pdf/main.cpp index 44257b50f5..4e6ec60388 100644 --- a/src/calibre/ebooks/pdf/main.cpp +++ b/src/calibre/ebooks/pdf/main.cpp @@ -1,3 +1,10 @@ +/** + * Copyright 2009 Kovid Goyal + * License: GNU GPL v2+ + */ + + + #ifndef PDF2XML #define UNICODE #define PY_SSIZE_T_CLEAN diff --git a/src/calibre/ebooks/pdf/reflow.cpp b/src/calibre/ebooks/pdf/reflow.cpp index c08d7e5507..0c569fe0d1 100644 --- a/src/calibre/ebooks/pdf/reflow.cpp +++ b/src/calibre/ebooks/pdf/reflow.cpp @@ -1,6 +1,6 @@ /** * Copyright 2009 Kovid Goyal - * License: GNU GPL v3 + * License: GNU GPL v2+ */ #include diff --git a/src/calibre/ebooks/pdf/reflow.h b/src/calibre/ebooks/pdf/reflow.h index deb1dec326..ad4b79929d 100644 --- a/src/calibre/ebooks/pdf/reflow.h +++ b/src/calibre/ebooks/pdf/reflow.h @@ -1,6 +1,6 @@ /** * Copyright 2009 Kovid Goyal - * License: GNU GPL v3 + * License: GNU GPL v2+ * Based on pdftohtml from the poppler project. */ diff --git a/src/calibre/ebooks/pdf/utils.h b/src/calibre/ebooks/pdf/utils.h index 43f435b1e3..4246239ac7 100644 --- a/src/calibre/ebooks/pdf/utils.h +++ b/src/calibre/ebooks/pdf/utils.h @@ -1,6 +1,6 @@ /** * Copyright 2009 Kovid Goyal - * License: GNU GPL v3 + * License: GNU GPL v2+ */ From 24a4261378a0f5ac7232bcb6e6d6a651491b60dc Mon Sep 17 00:00:00 2001 From: John Schember Date: Mon, 27 Dec 2010 06:58:39 -0500 Subject: [PATCH 03/26] PDF Output: Add missing option when generating the PDF Printer for comics. --- src/calibre/ebooks/pdf/writer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/ebooks/pdf/writer.py b/src/calibre/ebooks/pdf/writer.py index 2ae1638a73..2b4ba35d3e 100644 --- a/src/calibre/ebooks/pdf/writer.py +++ b/src/calibre/ebooks/pdf/writer.py @@ -217,7 +217,7 @@ class ImagePDFWriter(object): os.remove(f.name) def render_images(self, outpath, mi, items): - printer = get_pdf_printer(self.opts) + printer = get_pdf_printer(self.opts, for_comic=True) printer.setOutputFileName(outpath) printer.setDocName(mi.title) printer.setCreator(u'%s [%s]'%(__appname__, __version__)) From b87d3eb24882beb16cf2e33bb736884a8f6aa491 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 27 Dec 2010 10:17:27 -0700 Subject: [PATCH 04/26] Updated Heraldo de Aragon --- resources/recipes/heraldo.recipe | 73 +++++++++++++++++++------------- 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/resources/recipes/heraldo.recipe b/resources/recipes/heraldo.recipe index 381e97b9ce..c5669e116b 100644 --- a/resources/recipes/heraldo.recipe +++ b/resources/recipes/heraldo.recipe @@ -1,50 +1,65 @@ #!/usr/bin/env python -__license__ = 'GPL v3' -__author__ = 'Lorenzo Vigentini' -__copyright__ = '2009, Lorenzo Vigentini ' +__license__ = 'GPL v3' +__copyright__ = '04 December 2010, desUBIKado' +__author__ = 'desUBIKado' __description__ = 'Daily newspaper from Aragon' -__version__ = 'v1.01' -__date__ = '30, January 2010' - +__version__ = 'v0.03' +__date__ = '11, December 2010' ''' -http://www.heraldo.es/ +[url]http://www.heraldo.es/[/url] ''' +import time from calibre.web.feeds.news import BasicNewsRecipe class heraldo(BasicNewsRecipe): - author = 'Lorenzo Vigentini' + __author__ = 'desUBIKado' description = 'Daily newspaper from Aragon' - - cover_url = 'http://www.heraldo.es/MODULOS/global/publico/interfaces/img/logo.gif' title = u'Heraldo de Aragon' publisher = 'OJD Nielsen' category = 'News, politics, culture, economy, general interest' - language = 'es' timefmt = '[%a, %d %b, %Y]' - oldest_article = 1 - max_articles_per_feed = 25 - + max_articles_per_feed = 100 use_embedded_content = False - recursion = 10 - remove_javascript = True no_stylesheets = True - - keep_only_tags = [ - dict(name='div', attrs={'class':['titularNoticiaNN','textoGrisVerdanaContenidos']}) - ] + recursion = 10 feeds = [ - (u'Portadas ', u'http://www.heraldo.es/index.php/mod.portadas/mem.rss') - ] + (u'Portadas', u'http://www.heraldo.es/index.php/mod.portadas/mem.rss') + ] + + + + keep_only_tags = [dict(name='div', attrs={'id':['dts','com']})] + + remove_tags = [dict(name='a', attrs={'class':['com flo-r','enl-if','enl-df']}), + dict(name='div', attrs={'class':['brb-b-s con marg-btt','cnt-rel con']}), + dict(name='form', attrs={'class':'form'})] + + remove_tags_before = dict(name='div' , attrs={'id':'dts'}) + remove_tags_after = dict(name='div' , attrs={'id':'com'}) + + def get_cover_url(self): + cover = None + st = time.localtime() + year = str(st.tm_year) + month = "%.2d" % st.tm_mon + day = "%.2d" % st.tm_mday + #[url]http://oldorigin-www.heraldo.es/20101211/primeras/portada_aragon.pdf[/url] + cover='http://oldorigin-www.heraldo.es/'+ year + month + day +'/primeras/portada_aragon.pdf' + br = BasicNewsRecipe.get_browser() + try: + br.open(cover) + except: + self.log("\nPortada no disponible") + cover ='http://www.heraldo.es/MODULOS/global/publico/interfaces/img/logo-Heraldo.png' + return cover + + + extra_css = ''' - .articledate {color: gray;font-family: monospace;} - .articledescription {display: block;font-family: sans;font-size: 0.7em; text-indent: 0;} - .firma {color: #666;display: block;font-family: verdana, arial, helvetica;font-size: 1em;margin-bottom: 8px;} - .textoGrisVerdanaContenidos {color: #56595c;display: block;font-family: Verdana;font-size: 1.28571em;padding-bottom: 10px} - .titularNoticiaNN {display: block;padding-bottom: 10px;padding-left: 0;padding-right: 0;padding-top: 4px} - .titulo {color: #003066;font-family: Tahoma;font-size: 1.92857em;font-weight: bold;line-height: 1.2em} - ''' + h2{font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:xx-large;} + ''' From 9ad49466f74975cd704581b815638b3cdd2ac052 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 27 Dec 2010 10:50:32 -0700 Subject: [PATCH 05/26] El Periodico and Red Aragon by desUBIKado --- resources/recipes/el_periodico.recipe | 109 ++++++++++++++++++++++++++ resources/recipes/red_aragon.recipe | 47 +++++++++++ 2 files changed, 156 insertions(+) create mode 100644 resources/recipes/el_periodico.recipe create mode 100644 resources/recipes/red_aragon.recipe diff --git a/resources/recipes/el_periodico.recipe b/resources/recipes/el_periodico.recipe new file mode 100644 index 0000000000..2c3ed456fb --- /dev/null +++ b/resources/recipes/el_periodico.recipe @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__license__ = 'GPL v3' +__copyright__ = '04 December 2010, desUBIKado' +__author__ = 'desUBIKado' +__description__ = 'Daily newspaper from Aragon' +__version__ = 'v0.05' +__date__ = '07, December 2010' +''' +elperiodicodearagon.com +''' +import re +from calibre.web.feeds.news import BasicNewsRecipe + + +class elperiodicodearagon(BasicNewsRecipe): + title = u'El Periodico de Aragon' + __author__ = u'desUBIKado' + description = u'Noticias desde Aragon' + publisher = u'elperiodicodearagon.com' + category = u'news, politics, Spain, Aragon' + oldest_article = 2 + delay = 0 + max_articles_per_feed = 100 + no_stylesheets = True + use_embedded_content = False + language = 'es' + encoding = 'utf8' + remove_empty_feeds = True + remove_javascript = True + + + conversion_options = { + 'comments' : description + ,'tags' : category + ,'language' : language + ,'publisher' : publisher + } + + feeds = [(u'Arag\xf3n', u'http://elperiodicodearagon.com/RSS/2.xml'), + (u'Internacional', u'http://elperiodicodearagon.com/RSS/4.xml'), + (u'Espa\xf1a', u'http://elperiodicodearagon.com/RSS/3.xml'), + (u'Econom\xeda', u'http://elperiodicodearagon.com/RSS/5.xml'), + (u'Deportes', u'http://elperiodicodearagon.com/RSS/7.xml'), + (u'Real Zaragoza', u'http://elperiodicodearagon.com/RSS/10.xml'), + (u'Opini\xf3n', u'http://elperiodicodearagon.com/RSS/103.xml'), + (u'Escenarios', u'http://elperiodicodearagon.com/RSS/105.xml'), + (u'Sociedad', u'http://elperiodicodearagon.com/RSS/104.xml'), + (u'Gente', u'http://elperiodicodearagon.com/RSS/330.xml')] + + + extra_css = ''' + h3{font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:xx-large;} + h2{font-family:Arial,Helvetica,sans-serif; font-weight:normal;font-size:small;} + dd{font-family:Arial,Helvetica,sans-serif; font-weight:normal;font-size:small;} + ''' + + remove_attributes = ['height','width'] + + keep_only_tags = [dict(name='div', attrs={'id':'contenidos'})] + + + # Quitar toda la morralla + + remove_tags = [dict(name='ul', attrs={'class':'herramientasDeNoticia'}), + dict(name='span', attrs={'class':'MasInformacion '}), + dict(name='span', attrs={'class':'MasInformacion'}), + dict(name='div', attrs={'class':'Middle'}), + dict(name='div', attrs={'class':'MenuCabeceraRZaragoza'}), + dict(name='div', attrs={'id':'MenuCabeceraRZaragoza'}), + dict(name='div', attrs={'class':'MenuEquipo'}), + dict(name='div', attrs={'class':'TemasRelacionados'}), + dict(name='div', attrs={'class':'GaleriaEnNoticia'}), + dict(name='div', attrs={'class':'Recorte'}), + dict(name='div', attrs={'id':'NoticiasenRecursos'}), + dict(name='div', attrs={'id':'NoticiaEnPapel'}), + dict(name='p', attrs={'class':'RecorteEnNoticias'}), + dict(name='div', attrs={'id':'Comparte'}), + dict(name='div', attrs={'id':'CajaComparte'}), + dict(name='a', attrs={'class':'EscribirComentario'}), + dict(name='a', attrs={'class':'AvisoComentario'}), + dict(name='div', attrs={'class':'CajaAvisoComentario'}), + dict(name='div', attrs={'class':'navegaNoticias'}), + dict(name='div', attrs={'id':'PaginadorDiCom'}), + dict(name='div', attrs={'id':'CajaAccesoCuentaUsuario'}), + dict(name='div', attrs={'id':'CintilloComentario'}), + dict(name='div', attrs={'id':'EscribeComentario'}), + dict(name='div', attrs={'id':'FormularioComentario'}), + dict(name='div', attrs={'id':'FormularioNormas'})] + + # Recuperamos la portada de papel (la imagen format=1 tiene mayor resolucion) + + def get_cover_url(self): + index = 'http://pdf.elperiodicodearagon.com/' + soup = self.index_to_soup(index) + for image in soup.findAll('img',src=True): + if image['src'].startswith('http://pdf.elperiodicodearagon.com/funciones/portada-preview.php?eid='): + return image['src'].rstrip('format=2') + 'format=1' + return None + + # Para quitar espacios entre la noticia y los comentarios (lineas 1 y 2) + # El indice no apuntaba correctamente al empiece de la noticia (linea 3) + + preprocess_regexps = [ + (re.compile(r'

 

', re.DOTALL|re.IGNORECASE), lambda match: ''), + (re.compile(r'

', re.DOTALL|re.IGNORECASE), lambda match: ''), + (re.compile(r'

', re.DOTALL|re.IGNORECASE), lambda match: '

') + ] diff --git a/resources/recipes/red_aragon.recipe b/resources/recipes/red_aragon.recipe new file mode 100644 index 0000000000..4681e6660b --- /dev/null +++ b/resources/recipes/red_aragon.recipe @@ -0,0 +1,47 @@ +#!/usr/bin/env python +__license__ = 'GPL v3' +__copyright__ = '11 December 2010, desUBIKado' +__author__ = 'desUBIKado' +__description__ = 'Entertainment guide from Aragon' +__version__ = 'v0.01' +__date__ = '11, December 2010' +''' +[url]http://www.redaragon.es/[/url] +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class heraldo(BasicNewsRecipe): + __author__ = 'desUBIKado' + description = u'Guia de ocio desde Aragon' + title = u'RedAragon' + publisher = 'Grupo Z' + category = 'Concerts, Movies, Entertainment news' + cover_url = 'http://www.redaragon.com/2008_img/logotipo.gif' + language = 'es' + timefmt = '[%a, %d %b, %Y]' + oldest_article = 15 + max_articles_per_feed = 100 + encoding = 'iso-8859-1' + use_embedded_content = False + remove_javascript = True + no_stylesheets = True + + feeds = [(u'Conciertos', u'http://redaragon.com/rss/agenda.asp?tid=1'), + (u'Exposiciones', u'http://redaragon.com/rss/agenda.asp?tid=5'), + (u'Teatro', u'http://redaragon.com/rss/agenda.asp?tid=10'), + (u'Conferencias', u'http://redaragon.com/rss/agenda.asp?tid=2'), + (u'Ferias', u'http://redaragon.com/rss/agenda.asp?tid=6'), + (u'Filmotecas/Cineclubs', u'http://redaragon.com/rss/agenda.asp?tid=7'), + (u'Presentaciones', u'http://redaragon.com/rss/agenda.asp?tid=9'), + (u'Fiestas', u'http://redaragon.com/rss/agenda.asp?tid=11'), + (u'Infantil', u'http://redaragon.com/rss/agenda.asp?tid=13'), + (u'Otros', u'http://redaragon.com/rss/agenda.asp?tid=8')] + + keep_only_tags = [dict(name='div', attrs={'id':'FichaEventoAgenda'})] + + remove_tags = [dict(name='div', attrs={'class':['Comparte','CajaAgenda','Caja','Cintillo']})] + + remove_tags_before = dict(name='div' , attrs={'id':'FichaEventoAgenda'}) + + remove_tags_after = dict(name='div' , attrs={'class':'Cintillo'}) From 9a16081b0caffc11b62d9b10af2985e73ac8faec Mon Sep 17 00:00:00 2001 From: Li Fanxi Date: Wed, 29 Dec 2010 03:14:59 +0800 Subject: [PATCH 06/26] [Device] Add non-USB (Wi-Fi) connection support for Bambook. --- src/calibre/devices/bambook/driver.py | 24 +++++++++++++++++-- src/calibre/devices/bambook/libbambookcore.py | 2 ++ src/calibre/gui2/actions/device.py | 18 ++++++++++++++ src/calibre/gui2/device.py | 5 ++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/calibre/devices/bambook/driver.py b/src/calibre/devices/bambook/driver.py index 930c67a159..94a19df998 100644 --- a/src/calibre/devices/bambook/driver.py +++ b/src/calibre/devices/bambook/driver.py @@ -29,12 +29,15 @@ class BAMBOOK(DeviceConfig, DevicePlugin): booklist_class = BookList book_class = Book + ip = None + FORMATS = [ "snb" ] VENDOR_ID = 0x230b PRODUCT_ID = 0x0001 BCD = None CAN_SET_METADATA = False THUMBNAIL_HEIGHT = 155 + EXTRA_CUSTOMIZATION_MESSAGE = _("Device IP Address") icon = I("devices/bambook.png") # OPEN_FEEDBACK_MESSAGE = _( @@ -47,6 +50,10 @@ class BAMBOOK(DeviceConfig, DevicePlugin): METADATA_FILE_GUID = 'calibremetadata.snb' bambook = None + is_connected = False + + def __init__(self, ip): + self.ip = ip def reset(self, key='-1', log_packets=False, report_progress=None, detected_device=None) : @@ -60,15 +67,23 @@ class BAMBOOK(DeviceConfig, DevicePlugin): self.eject() # Connect self.bambook = Bambook() - self.bambook.Connect() + self.bambook.Connect(ip = self.ip, timeout = 10000) if self.bambook.GetState() != CONN_CONNECTED: self.bambook = None - raise Exception(_("Unable to connect to Bambook.")) + raise OpenFeedback(_("Unable to connect to Bambook. \n" + "If you are trying to connect via Wi-Fi, " + "please make sure the IP address of Bambook has been correctly configured.")) + self.is_connected = True + return True + + def unmount_device(self): + self.eject() def eject(self): if self.bambook: self.bambook.Disconnect() self.bambook = None + self.is_connected = False def post_yank_cleanup(self): self.eject() @@ -475,3 +490,8 @@ class BAMBOOK(DeviceConfig, DevicePlugin): def get_guid(uuid): guid = hashlib.md5(uuid).hexdigest()[0:15] + ".snb" return guid + +class BAMBOOKWifi(BAMBOOK): + def is_usb_connected(self, devices_on_system, debug=False, + only_presence=False): + return self.is_connected, self diff --git a/src/calibre/devices/bambook/libbambookcore.py b/src/calibre/devices/bambook/libbambookcore.py index a11c5e9e87..35d04ba4ac 100644 --- a/src/calibre/devices/bambook/libbambookcore.py +++ b/src/calibre/devices/bambook/libbambookcore.py @@ -329,6 +329,8 @@ class Bambook: self.handle = None def Connect(self, ip = DEFAULT_BAMBOOK_IP, timeout = 10000): + if ip == None or ip == '': + ip = DEFAULT_BAMBOOK_IP self.handle = BambookConnect(ip, timeout) if self.handle and self.handle != 0: return True diff --git a/src/calibre/gui2/actions/device.py b/src/calibre/gui2/actions/device.py index 744ab20d10..35bfd2bf6a 100644 --- a/src/calibre/gui2/actions/device.py +++ b/src/calibre/gui2/actions/device.py @@ -12,11 +12,15 @@ from PyQt4.Qt import QToolButton, QMenu, pyqtSignal, QIcon from calibre.gui2.actions import InterfaceAction from calibre.utils.smtp import config as email_config from calibre.constants import iswindows, isosx +from calibre.customize.ui import is_disabled +from calibre.devices.bambook.driver import BAMBOOK class ShareConnMenu(QMenu): # {{{ connect_to_folder = pyqtSignal() connect_to_itunes = pyqtSignal() + connect_to_bambook = pyqtSignal() + config_email = pyqtSignal() toggle_server = pyqtSignal() dont_add_to = frozenset(['toolbar-device', 'context-menu-device']) @@ -34,6 +38,12 @@ class ShareConnMenu(QMenu): # {{{ self.connect_to_itunes_action = mitem if not (iswindows or isosx): mitem.setVisible(False) + mitem = self.addAction(QIcon(I('devices/bambook.png')), _('Connect to Bambook')) + mitem.setEnabled(True) + mitem.triggered.connect(lambda x : self.connect_to_bambook.emit()) + self.connect_to_bambook_action = mitem + if is_disabled(BAMBOOK): + mitem.setVisible(False) self.addSeparator() self.toggle_server_action = \ self.addAction(QIcon(I('network-server.png')), @@ -88,6 +98,13 @@ class ShareConnMenu(QMenu): # {{{ def set_state(self, device_connected): self.connect_to_folder_action.setEnabled(not device_connected) self.connect_to_itunes_action.setEnabled(not device_connected) + self.connect_to_bambook_action.setEnabled(not device_connected) + bambook_visible = False + if not is_disabled(BAMBOOK): + device_ip = BAMBOOK.settings().extra_customization + if device_ip != None and device_ip != '': + bambook_visible = True + self.connect_to_bambook_action.setVisible(bambook_visible) # }}} @@ -126,6 +143,7 @@ class ConnectShareAction(InterfaceAction): self.qaction.setMenu(self.share_conn_menu) self.share_conn_menu.connect_to_folder.connect(self.gui.connect_to_folder) self.share_conn_menu.connect_to_itunes.connect(self.gui.connect_to_itunes) + self.share_conn_menu.connect_to_bambook.connect(self.gui.connect_to_bambook) def location_selected(self, loc): enabled = loc == 'library' diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 3b071aa024..6d289a3e5c 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -24,6 +24,7 @@ from calibre.utils.filenames import ascii_filename from calibre.devices.errors import FreeSpaceError from calibre.devices.apple.driver import ITUNES_ASYNC from calibre.devices.folder_device.driver import FOLDER_DEVICE +from calibre.devices.bambook.driver import BAMBOOK, BAMBOOKWifi from calibre.ebooks.metadata.meta import set_metadata from calibre.constants import DEBUG from calibre.utils.config import prefs, tweaks @@ -635,6 +636,10 @@ class DeviceMixin(object): # {{{ if dir is not None: self.device_manager.mount_device(kls=FOLDER_DEVICE, kind='folder', path=dir) + def connect_to_bambook(self): + self.device_manager.mount_device(kls=BAMBOOKWifi, kind='bambook', + path=BAMBOOK.settings().extra_customization) + def connect_to_itunes(self): self.device_manager.mount_device(kls=ITUNES_ASYNC, kind='itunes', path=None) From 773ee07343dfb9c904438723f79e287db9f8529c Mon Sep 17 00:00:00 2001 From: Li Fanxi Date: Wed, 29 Dec 2010 22:36:31 +0800 Subject: [PATCH 07/26] [Bug] Better error handling if some meta data is missing in the SNB file. --- src/calibre/ebooks/snb/input.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/calibre/ebooks/snb/input.py b/src/calibre/ebooks/snb/input.py index 659ca79619..d2acb257aa 100755 --- a/src/calibre/ebooks/snb/input.py +++ b/src/calibre/ebooks/snb/input.py @@ -46,14 +46,27 @@ class SNBInput(InputFormatPlugin): meta = snbFile.GetFileStream('snbf/book.snbf') if meta != None: meta = etree.fromstring(meta) - oeb.metadata.add('title', meta.find('.//head/name').text) - oeb.metadata.add('creator', meta.find('.//head/author').text, attrib={'role':'aut'}) - oeb.metadata.add('language', meta.find('.//head/language').text.lower().replace('_', '-')) - oeb.metadata.add('creator', meta.find('.//head/generator').text) - oeb.metadata.add('publisher', meta.find('.//head/publisher').text) - cover = meta.find('.//head/cover') - if cover != None and cover.text != None: - oeb.guide.add('cover', 'Cover', cover.text) + l = { 'title' : './/head/name', + 'creator' : './/head/author', + 'language' : './/head/language', + 'generator': './/head/generator', + 'publisher': './/head/publisher', + 'cover' : './/head/cover', } + d = {} + for item in l: + node = meta.find(l[item]) + if node != None: + d[item] = node.text if node.text != None else '' + else: + d[item] = '' + + oeb.metadata.add('title', d['title']) + oeb.metadata.add('creator', d['creator'], attrib={'role':'aut'}) + oeb.metadata.add('language', d['language'].lower().replace('_', '-')) + oeb.metadata.add('generator', d['generator']) + oeb.metadata.add('publisher', d['publisher']) + if d['cover'] != '': + oeb.guide.add('cover', 'Cover', d['cover']) bookid = str(uuid.uuid4()) oeb.metadata.add('identifier', bookid, id='uuid_id', scheme='uuid') From e24150ade3b84f72e72ce009bae9a00aef7662d2 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 29 Dec 2010 11:17:04 -0700 Subject: [PATCH 08/26] Fix #8102 (Updated recipe for Wired Magazine) --- resources/recipes/wired.recipe | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/resources/recipes/wired.recipe b/resources/recipes/wired.recipe index 9599d54de9..bb9a97f5c4 100644 --- a/resources/recipes/wired.recipe +++ b/resources/recipes/wired.recipe @@ -38,12 +38,12 @@ class Wired(BasicNewsRecipe): keep_only_tags = [dict(name='div', attrs={'class':'post'})] remove_tags_after = dict(name='div', attrs={'class':'tweetmeme_button'}) remove_tags = [ - dict(name=['object','embed','iframe','link']) + dict(name=['object','embed','iframe','link','meta','base']) ,dict(name='div', attrs={'class':['podcast_storyboard','tweetmeme_button']}) ,dict(attrs={'id':'ff_bottom_nav'}) ,dict(name='a',attrs={'href':'http://www.wired.com/app'}) ] - remove_attributes = ['height','width'] + remove_attributes = ['height','width','lang','border','clear'] def parse_index(self): @@ -78,7 +78,9 @@ class Wired(BasicNewsRecipe): divurl = item.find('div',attrs={'class':'feature-header'}) if divurl: divdesc = item.find('div',attrs={'class':'feature-text'}) - url = 'http://www.wired.com' + divurl.a['href'] + url = divurl.a['href'] + if not divurl.a['href'].startswith('http://www.wired.com'): + url = 'http://www.wired.com' + divurl.a['href'] title = self.tag_to_string(divurl.a) description = self.tag_to_string(divdesc) date = strftime(self.timefmt) @@ -127,5 +129,17 @@ class Wired(BasicNewsRecipe): def preprocess_html(self, soup): for item in soup.findAll(style=True): del item['style'] + for item in soup.findAll('a'): + if item.string is not None: + tstr = item.string + item.replaceWith(tstr) + else: + item.name='span' + for atrs in ['href','target','alt','title','name','id']: + if item.has_key(atrs): + del item[atrs] + for item in soup.findAll('img'): + if not item.has_key('alt'): + item['alt'] = 'image' return soup From 14fa34a4fb0dfe25a753030adda038f9c5640c63 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 29 Dec 2010 11:26:35 -0700 Subject: [PATCH 09/26] Business Insider by DM. Fixes #8087 (New recipe for Business insider) --- resources/images/news/business_insider.png | Bin 0 -> 1147 bytes resources/recipes/business_insider.recipe | 69 +++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 resources/images/news/business_insider.png create mode 100644 resources/recipes/business_insider.recipe diff --git a/resources/images/news/business_insider.png b/resources/images/news/business_insider.png new file mode 100644 index 0000000000000000000000000000000000000000..7e86e583e8f7b1d127561bfdce0b19d24536f15e GIT binary patch literal 1147 zcmV->1cdvEP)jx@mQ;UIZB-$VrwSp~(7DVynMSAGLi%5^2>fhkO zn+NfzAS#L#6)b29T2Vyf7k;$$gIJTaU2AIdu}Q|mIL>Yw5uMB1$ISfR@4feXvt;+~ zfq}t6Aw19XJP-f02nqT^{QZtPW15UH2C!4_VY-wp} z0e0-zu%WdTIB=k+XXj2J91ev-As~~<<)){BNF)?8O(36l-MKm7`t`ea@81VLeVUre zW_6%MA{J|J2lnmj?(XUW97p2j^RD~t8*t-BDm69+q|@)-jgJG=bqj_0c_5W~@+6%G zmM^z$+Xgy29VZq8?%jL*_~}#N^5r{sQYoOfciXmP5;%40#EIj_0n3U+!eM|ALI?p~ zy_%T#_z}qEW@lX&=k47~CWvkU%tya^eu2dwhil;2o7ggV+ zuY0L{X{V<0`I#A@T$Y;2(0f3*8TE$|yTrLCW&Rx59`!+B+naOYt{f~&Rn`QJPg!o^?JSDtd+{DO3Q>7iEwcrgW^1U_UhGJw}5BQ-oBlf0Q&p) z@87dWk6UAg%_`tenEw8tlG&d`sF;^Zl}e=oJb3W@`Rmt!VHk#C$g$nHQJ-rr!5|(X z0HZX>sQH!Pz7Rm6@Z-nAf z7&8pOwwEliEMWWg&70$K;Ne60u%y%P-%n2J0GxBqm?og`{P8FS80Qi=nRJ|ZT#uc4 zA&(sC>+9_WdV02Q-LeHRO$q$@b2d9Y4P3l9GBP?UMeBKh Date: Wed, 29 Dec 2010 11:35:48 -0700 Subject: [PATCH 10/26] Fix #8083 (HTC Desire + DeFrost ROM not recognized by Android driver.) --- src/calibre/devices/android/driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/devices/android/driver.py b/src/calibre/devices/android/driver.py index 492b00617d..ced6a45da4 100644 --- a/src/calibre/devices/android/driver.py +++ b/src/calibre/devices/android/driver.py @@ -64,7 +64,7 @@ class ANDROID(USBMS): WINDOWS_MAIN_MEM = ['ANDROID_PHONE', 'A855', 'A853', 'INC.NEXUS_ONE', '__UMS_COMPOSITE', '_MB200', 'MASS_STORAGE', '_-_CARD', 'SGH-I897', 'GT-I9000', 'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', - 'SCH-I500_CARD', 'SPH-D700_CARD', 'MB810', 'GT-P1000'] + 'SCH-I500_CARD', 'SPH-D700_CARD', 'MB810', 'GT-P1000', 'DESIRE'] WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897', 'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD'] From 85bf7da1fb9fc6d695f7e89d2d82d96fa484440e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 29 Dec 2010 11:49:05 -0700 Subject: [PATCH 11/26] Fix #8054 (Hyperlinks in book descriptions don't work) --- src/calibre/gui2/book_details.py | 10 ++++++++-- src/calibre/gui2/dialogs/book_info.py | 7 ++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/calibre/gui2/book_details.py b/src/calibre/gui2/book_details.py index dd12080d7f..8e3e8b10de 100644 --- a/src/calibre/gui2/book_details.py +++ b/src/calibre/gui2/book_details.py @@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en' import os, collections, sys from Queue import Queue -from PyQt4.Qt import QPixmap, QSize, QWidget, Qt, pyqtSignal, \ +from PyQt4.Qt import QPixmap, QSize, QWidget, Qt, pyqtSignal, QUrl, \ QPropertyAnimation, QEasingCurve, QThread, QApplication, QFontInfo, \ QSizePolicy, QPainter, QRect, pyqtProperty, QLayout, QPalette from PyQt4.QtWebKit import QWebView @@ -18,7 +18,7 @@ from calibre.gui2.widgets import IMAGE_EXTENSIONS from calibre.ebooks import BOOK_EXTENSIONS from calibre.constants import preferred_encoding from calibre.library.comments import comments_to_html -from calibre.gui2 import config, open_local_file +from calibre.gui2 import config, open_local_file, open_url from calibre.utils.icu import sort_key # render_rows(data) {{{ @@ -412,6 +412,12 @@ class BookDetails(QWidget): # {{{ self.view_specific_format.emit(int(id_), fmt) elif typ == 'devpath': open_local_file(val) + else: + try: + open_url(QUrl(link, QUrl.TolerantMode)) + except: + import traceback + traceback.print_exc() def mouseDoubleClickEvent(self, ev): diff --git a/src/calibre/gui2/dialogs/book_info.py b/src/calibre/gui2/dialogs/book_info.py index 1384c27b8c..eac8461299 100644 --- a/src/calibre/gui2/dialogs/book_info.py +++ b/src/calibre/gui2/dialogs/book_info.py @@ -9,7 +9,7 @@ from PyQt4.Qt import QCoreApplication, SIGNAL, QModelIndex, QTimer, Qt, \ QDialog, QPixmap, QGraphicsScene, QIcon, QSize from calibre.gui2.dialogs.book_info_ui import Ui_BookInfo -from calibre.gui2 import dynamic, open_local_file +from calibre.gui2 import dynamic, open_local_file, open_url from calibre import fit_image from calibre.library.comments import comments_to_html from calibre.utils.icu import sort_key @@ -22,6 +22,8 @@ class BookInfo(QDialog, Ui_BookInfo): self.setupUi(self) self.cover_pixmap = None self.comments.sizeHint = self.comments_size_hint + self.comments.page().setLinkDelegationPolicy(self.comments.page().DelegateAllLinks) + self.comments.linkClicked(self.link_clicked) self.view_func = view_func @@ -41,6 +43,8 @@ class BookInfo(QDialog, Ui_BookInfo): screen_height = desktop.availableGeometry().height() - 100 self.resize(self.size().width(), screen_height) + def link_clicked(self, url): + open_url(url) def comments_size_hint(self): return QSize(350, 250) @@ -115,6 +119,7 @@ class BookInfo(QDialog, Ui_BookInfo): lines = [x if x.strip() else '

' for x in lines] comments = '\n'.join(lines) self.comments.setHtml('

%s
' % comments) + self.comments.page().setLinkDelegationPolicy(self.comments.page().DelegateAllLinks) cdata = info.pop('cover', '') self.cover_pixmap = QPixmap.fromImage(cdata) self.resize_cover() From a323051dcdf436c7eb87b41fec06a1b9e3a23c20 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 29 Dec 2010 11:51:59 -0700 Subject: [PATCH 12/26] (Imroved El Pais) Fix #8095 (Completely new recipe for El Pais) --- resources/recipes/elpais_impreso.recipe | 141 +++++++++++++----------- 1 file changed, 75 insertions(+), 66 deletions(-) diff --git a/resources/recipes/elpais_impreso.recipe b/resources/recipes/elpais_impreso.recipe index bba3bda217..130013286c 100644 --- a/resources/recipes/elpais_impreso.recipe +++ b/resources/recipes/elpais_impreso.recipe @@ -1,86 +1,95 @@ -# -*- coding: utf-8 -*- __license__ = 'GPL v3' __copyright__ = '2010, Darko Miletic ' ''' -www.elpais.com/diario/ +www.elpais.com ''' -from calibre import strftime from calibre.web.feeds.news import BasicNewsRecipe -class ElPaisImpresa(BasicNewsRecipe): - title = u'El Pa\xeds - edicion impresa' +class ElPais_RSS(BasicNewsRecipe): + title = 'El Pais' __author__ = 'Darko Miletic' - description = u'el periodico global en Espa\xf1ol' + description = 'el periodico global en Castellano' publisher = 'EDICIONES EL PAIS, S.L.' - category = 'news, politics,Spain,actualidad,noticias,informacion,videos,fotografias,audios,graficos,nacional,internacional,deportes,economia,tecnologia,cultura,gente,television,sociedad,opinion,blogs,foros,chats,encuestas,entrevistas,participacion' + category = 'news, politics, finances, world, spain' + oldest_article = 2 + max_articles_per_feed = 200 no_stylesheets = True - encoding = 'latin1' + encoding = 'cp1252' use_embedded_content = False - language = 'es' + language = 'es_ES' + remove_empty_feeds = True publication_type = 'newspaper' - masthead_url = 'http://www.elpais.com/im/tit_logo_global.gif' - index = 'http://www.elpais.com/diario/' - extra_css = ' p{text-align: justify} body{ text-align: left; font-family: Georgia,"Times New Roman",Times,serif } h2{font-family: Arial,Helvetica,sans-serif} img{margin-bottom: 0.4em} ' + masthead_url = 'http://www.elpais.com/im/tit_logo.gif' + extra_css = """ + body{font-family: Georgia,"Times New Roman",Times,serif } + h3{font-family: Arial,Helvetica,sans-serif} + img{margin-bottom: 0.4em; display:block} + """ conversion_options = { - 'comment' : description - , 'tags' : category - , 'publisher' : publisher - , 'language' : language + 'comment' : description + , 'tags' : category + , 'publisher' : publisher + , 'language' : language } - feeds = [ - (u'Internacional' , index + u'internacional/' ) - ,(u'Espa\xf1a' , index + u'espana/' ) - ,(u'Economia' , index + u'economia/' ) - ,(u'Opinion' , index + u'opinion/' ) - ,(u'Vi\xf1etas' , index + u'vineta/' ) - ,(u'Sociedad' , index + u'sociedad/' ) - ,(u'Cultura' , index + u'cultura/' ) - ,(u'Tendencias' , index + u'tendencias/' ) - ,(u'Gente' , index + u'gente/' ) - ,(u'Obituarios' , index + u'obituarios/' ) - ,(u'Deportes' , index + u'deportes/' ) - ,(u'Pantallas' , index + u'radioytv/' ) - ,(u'Ultima' , index + u'ultima/' ) - ,(u'Educacion' , index + u'educacion/' ) - ,(u'Saludo' , index + u'salud/' ) - ,(u'Ciberpais' , index + u'ciberpais/' ) - ,(u'EP3' , index + u'ep3/' ) - ,(u'Cine' , index + u'cine/' ) - ,(u'Babelia' , index + u'babelia/' ) - ,(u'El viajero' , index + u'viajero/' ) - ,(u'Negocios' , index + u'negocios/' ) - ,(u'Domingo' , index + u'domingo/' ) - ,(u'El Pais semanal' , index + u'eps/' ) - ,(u'Quadern Catalunya' , index + u'quadern-catalunya/' ) - ] + keep_only_tags = [dict(attrs={'class':['cabecera_noticia estirar','cabecera_noticia','','contenido_noticia']})] + remove_tags = [ + dict(name=['meta','link','base','iframe','embed','object']) + ,dict(attrs={'class':['info_complementa','estructura_2col_der','votos estirar','votos']}) + ,dict(attrs={'id':'utilidades'}) + ] + remove_tags_after = dict(attrs={'id':'utilidades'}) + remove_attributes = ['lang','border','width','height'] - keep_only_tags=[dict(attrs={'class':['cabecera_noticia','contenido_noticia']})] - remove_attributes=['width','height'] - remove_tags=[dict(name='link')] - - def parse_index(self): - totalfeeds = [] - lfeeds = self.get_feeds() - for feedobj in lfeeds: - feedtitle, feedurl = feedobj - self.report_progress(0, _('Fetching feed')+' %s...'%(feedtitle if feedtitle else feedurl)) - articles = [] - soup = self.index_to_soup(feedurl) - for item in soup.findAll('a',attrs={'class':['g19r003','g19i003','g17r003','g17i003']}): - url = 'http://www.elpais.com' + item['href'].rpartition('/')[0] - title = self.tag_to_string(item) - date = strftime(self.timefmt) - articles.append({ - 'title' :title - ,'date' :date - ,'url' :url - ,'description':'' - }) - totalfeeds.append((feedtitle, articles)) - return totalfeeds + feeds = [ + (u'Lo ultimo' , u'http://www.elpais.com/rss/feed.html?feedId=17046') + ,(u'America Latina' , u'http://www.elpais.com/rss/feed.html?feedId=17041') + ,(u'Mexico' , u'http://www.elpais.com/rss/feed.html?feedId=17042') + ,(u'Europa' , u'http://www.elpais.com/rss/feed.html?feedId=17043') + ,(u'Estados Unidos' , u'http://www.elpais.com/rss/feed.html?feedId=17044') + ,(u'Oriente proximo' , u'http://www.elpais.com/rss/feed.html?feedId=17045') + ,(u'Espana' , u'http://www.elpais.com/rss/feed.html?feedId=1002' ) + ,(u'Andalucia' , u'http://www.elpais.com/rss/feed.html?feedId=17057') + ,(u'Catalunia' , u'http://www.elpais.com/rss/feed.html?feedId=17059') + ,(u'Comunidad Valenciana' , u'http://www.elpais.com/rss/feed.html?feedId=17061') + ,(u'Madrid' , u'http://www.elpais.com/rss/feed.html?feedId=1016' ) + ,(u'Pais Vasco' , u'http://www.elpais.com/rss/feed.html?feedId=17062') + ,(u'Galicia' , u'http://www.elpais.com/rss/feed.html?feedId=17063') + ,(u'Opinion' , u'http://www.elpais.com/rss/feed.html?feedId=1003' ) + ,(u'Sociedad' , u'http://www.elpais.com/rss/feed.html?feedId=1004' ) + ,(u'Deportes' , u'http://www.elpais.com/rss/feed.html?feedId=1007' ) + ,(u'Cultura' , u'http://www.elpais.com/rss/feed.html?feedId=1008' ) + ,(u'Cine' , u'http://www.elpais.com/rss/feed.html?feedId=17052') + ,(u'Literatura' , u'http://www.elpais.com/rss/feed.html?feedId=17053') + ,(u'Musica' , u'http://www.elpais.com/rss/feed.html?feedId=17051') + ,(u'Arte' , u'http://www.elpais.com/rss/feed.html?feedId=17060') + ,(u'Tecnologia' , u'http://www.elpais.com/rss/feed.html?feedId=1005' ) + ,(u'Economia' , u'http://www.elpais.com/rss/feed.html?feedId=1006' ) + ,(u'Ciencia' , u'http://www.elpais.com/rss/feed.html?feedId=17068') + ,(u'Salud' , u'http://www.elpais.com/rss/feed.html?feedId=17074') + ,(u'Ocio' , u'http://www.elpais.com/rss/feed.html?feedId=17075') + ,(u'Justicia y Leyes' , u'http://www.elpais.com/rss/feed.html?feedId=17069') + ,(u'Guerras y conflictos' , u'http://www.elpais.com/rss/feed.html?feedId=17070') + ,(u'Politica' , u'http://www.elpais.com/rss/feed.html?feedId=17073') + ] def print_version(self, url): return url + '?print=1' + + def preprocess_html(self, soup): + for item in soup.findAll(style=True): + del item['style'] + for item in soup.findAll('a'): + if item.string is not None: + tstr = item.string + item.replaceWith(tstr) + else: + item.name='span' + for atrs in ['href','target','alt','title']: + if item.has_key(atrs): + del item[atrs] + for item in soup.findAll('img',alt=False): + item['alt'] = 'image' + return soup From 459529d11bc3e1cb271ada1b83dc46c710f31582 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 29 Dec 2010 12:00:04 -0700 Subject: [PATCH 13/26] comments editor: Pass through Esc key --- src/calibre/gui2/comments_editor.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/calibre/gui2/comments_editor.py b/src/calibre/gui2/comments_editor.py index 97a218a10b..1a6b60284b 100644 --- a/src/calibre/gui2/comments_editor.py +++ b/src/calibre/gui2/comments_editor.py @@ -259,6 +259,19 @@ class EditorWidget(QWebView): # {{{ return property(fget=fget, fset=fset) + def keyPressEvent(self, ev): + if ev.key() in (Qt.Key_Tab, Qt.Key_Escape, Qt.Key_Backtab): + ev.ignore() + else: + return QWebView.keyPressed(self, ev) + + def keyReleaseEvent(self, ev): + if ev.key() in (Qt.Key_Tab, Qt.Key_Escape, Qt.Key_Backtab): + ev.ignore() + else: + return QWebView.keyReleased(self, ev) + + # }}} # Highlighter {{{ From c54b2f6776c8dfb288d803c47762536d7480082e Mon Sep 17 00:00:00 2001 From: John Schember Date: Wed, 29 Dec 2010 20:25:15 -0500 Subject: [PATCH 14/26] Add Output Encoding option (present on command line) to GUI for TXT, PDB and PMLZ Output formats. --- src/calibre/ebooks/pdf/writer.py | 2 +- src/calibre/ebooks/txt/output.py | 3 +-- src/calibre/gui2/convert/pdb_output.py | 2 +- src/calibre/gui2/convert/pdb_output.ui | 14 ++++++++++++-- src/calibre/gui2/convert/pml_output.py | 3 ++- src/calibre/gui2/convert/pmlz_output.ui | 16 +++++++++++++--- src/calibre/gui2/convert/txt_output.py | 3 ++- src/calibre/gui2/convert/txt_output.ui | 22 ++++++++++++++++------ 8 files changed, 48 insertions(+), 17 deletions(-) diff --git a/src/calibre/ebooks/pdf/writer.py b/src/calibre/ebooks/pdf/writer.py index 2b4ba35d3e..7af0ed05c9 100644 --- a/src/calibre/ebooks/pdf/writer.py +++ b/src/calibre/ebooks/pdf/writer.py @@ -57,7 +57,7 @@ def get_pdf_printer(opts, for_comic=False): h = opts.output_profile.comic_screen_size[1] if for_comic else \ opts.output_profile.height dpi = opts.output_profile.dpi - printer.setPaperSize(QSizeF(float(w) / dpi, float(h)/dpi), QPrinter.Inch) + printer.setPaperSize(QSizeF(float(w) / dpi, float(h) / dpi), QPrinter.Inch) printer.setPageMargins(opts.margin_left, opts.margin_top, opts.margin_right, opts.margin_bottom, QPrinter.Point) printer.setOrientation(orientation(opts.orientation)) diff --git a/src/calibre/ebooks/txt/output.py b/src/calibre/ebooks/txt/output.py index a6369b6f0b..0e077672d8 100644 --- a/src/calibre/ebooks/txt/output.py +++ b/src/calibre/ebooks/txt/output.py @@ -29,8 +29,7 @@ class TXTOutput(OutputFormatPlugin): OptionRecommendation(name='output_encoding', recommended_value='utf-8', level=OptionRecommendation.LOW, help=_('Specify the character encoding of the output document. ' \ - 'The default is utf-8. Note: This option is not honored by all ' \ - 'formats.')), + 'The default is utf-8.')), OptionRecommendation(name='inline_toc', recommended_value=False, level=OptionRecommendation.LOW, help=_('Add Table of Contents to beginning of the book.')), diff --git a/src/calibre/gui2/convert/pdb_output.py b/src/calibre/gui2/convert/pdb_output.py index 9f88656f2f..51c202cb03 100644 --- a/src/calibre/gui2/convert/pdb_output.py +++ b/src/calibre/gui2/convert/pdb_output.py @@ -19,7 +19,7 @@ class PluginWidget(Widget, Ui_Form): ICON = I('mimetypes/unknown.png') def __init__(self, parent, get_option, get_help, db=None, book_id=None): - Widget.__init__(self, parent, ['format', 'inline_toc']) + Widget.__init__(self, parent, ['format', 'inline_toc', 'output_encoding']) self.db, self.book_id = db, book_id self.initialize_options(get_option, get_help, db, book_id) diff --git a/src/calibre/gui2/convert/pdb_output.ui b/src/calibre/gui2/convert/pdb_output.ui index 772a19b79e..17bdc0a984 100644 --- a/src/calibre/gui2/convert/pdb_output.ui +++ b/src/calibre/gui2/convert/pdb_output.ui @@ -27,7 +27,7 @@ - + Qt::Vertical @@ -40,13 +40,23 @@ - + &Inline TOC + + + + Output Encoding: + + + + + + diff --git a/src/calibre/gui2/convert/pml_output.py b/src/calibre/gui2/convert/pml_output.py index 61207d3de5..f7905194ca 100644 --- a/src/calibre/gui2/convert/pml_output.py +++ b/src/calibre/gui2/convert/pml_output.py @@ -17,6 +17,7 @@ class PluginWidget(Widget, Ui_Form): ICON = I('mimetypes/unknown.png') def __init__(self, parent, get_option, get_help, db=None, book_id=None): - Widget.__init__(self, parent, ['inline_toc', 'full_image_depth']) + Widget.__init__(self, parent, ['inline_toc', 'full_image_depth', + 'output_encoding']) self.db, self.book_id = db, book_id self.initialize_options(get_option, get_help, db, book_id) diff --git a/src/calibre/gui2/convert/pmlz_output.ui b/src/calibre/gui2/convert/pmlz_output.ui index 3573e14210..9754752c8a 100644 --- a/src/calibre/gui2/convert/pmlz_output.ui +++ b/src/calibre/gui2/convert/pmlz_output.ui @@ -14,7 +14,7 @@ Form - + Qt::Vertical @@ -27,20 +27,30 @@ - + &Inline TOC - + Do not reduce image size and depth + + + + Output Encoding: + + + + + + diff --git a/src/calibre/gui2/convert/txt_output.py b/src/calibre/gui2/convert/txt_output.py index 2fafad4b43..9f30e0d83f 100644 --- a/src/calibre/gui2/convert/txt_output.py +++ b/src/calibre/gui2/convert/txt_output.py @@ -21,7 +21,8 @@ class PluginWidget(Widget, Ui_Form): def __init__(self, parent, get_option, get_help, db=None, book_id=None): Widget.__init__(self, parent, ['newline', 'max_line_length', 'force_max_line_length', - 'inline_toc', 'markdown_format', 'keep_links', 'keep_image_references']) + 'inline_toc', 'markdown_format', 'keep_links', 'keep_image_references', + 'output_encoding']) self.db, self.book_id = db, book_id self.initialize_options(get_option, get_help, db, book_id) diff --git a/src/calibre/gui2/convert/txt_output.ui b/src/calibre/gui2/convert/txt_output.ui index 19e4ec52a1..6290a096c8 100644 --- a/src/calibre/gui2/convert/txt_output.ui +++ b/src/calibre/gui2/convert/txt_output.ui @@ -27,7 +27,7 @@ - + Qt::Vertical @@ -40,7 +40,7 @@ - + &Inline TOC @@ -60,34 +60,44 @@ - + Force maximum line length - + Apply Markdown formatting to text - + Do not remove links (<a> tags) before processing - + Do not remove image references before processing + + + + Output Encoding: + + + + + + From 6931d463d4219327ddd1d14eee8c401e52f75150 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 30 Dec 2010 09:41:49 -0700 Subject: [PATCH 15/26] Fix #8088 (Support for Pocketbook Pro 603) --- src/calibre/devices/eb600/driver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/calibre/devices/eb600/driver.py b/src/calibre/devices/eb600/driver.py index 246b753fa8..de8455e595 100644 --- a/src/calibre/devices/eb600/driver.py +++ b/src/calibre/devices/eb600/driver.py @@ -230,7 +230,7 @@ class POCKETBOOK301(USBMS): class POCKETBOOK602(USBMS): name = 'PocketBook Pro 602/902 Device Interface' - description = _('Communicate with the PocketBook 602 reader.') + description = _('Communicate with the PocketBook 602/603/902 reader.') author = 'Kovid Goyal' supported_platforms = ['windows', 'osx', 'linux'] FORMATS = ['epub', 'fb2', 'prc', 'mobi', 'pdf', 'djvu', 'rtf', 'chm', @@ -244,7 +244,7 @@ class POCKETBOOK602(USBMS): BCD = [0x0324] VENDOR_NAME = '' - WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = ['PB602', 'PB902'] + WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = ['PB602', 'PB603', 'PB902'] class POCKETBOOK701(USBMS): From 60558691303d249328a025a8fb30a6c4e58910cf Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 30 Dec 2010 09:46:25 -0700 Subject: [PATCH 16/26] Fix #8111 (Feature request: Ability to choose working temp folder) --- src/calibre/manual/customize.rst | 1 + src/calibre/ptempfile.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/calibre/manual/customize.rst b/src/calibre/manual/customize.rst index d7b4e931d9..6218bf8112 100644 --- a/src/calibre/manual/customize.rst +++ b/src/calibre/manual/customize.rst @@ -21,6 +21,7 @@ Environment variables ----------------------- * ``CALIBRE_CONFIG_DIRECTORY`` - sets the directory where configuration files are stored/read. + * ``CALIBRE_TEMP_DIR`` - sets the temporary directory used by calibre * ``CALIBRE_OVERRIDE_DATABASE_PATH`` - allows you to specify the full path to metadata.db. Using this variable you can have metadata.db be in a location other than the library folder. Useful if your library folder is on a networked drive that does not support file locking. * ``CALIBRE_DEVELOP_FROM`` - Used to run from a calibre development environment. See :ref:`develop`. * ``CALIBRE_OVERRIDE_LANG`` - Used to force the language used by the interface (ISO 639 language code) diff --git a/src/calibre/ptempfile.py b/src/calibre/ptempfile.py index 71ae9b0789..ac7df1c4e3 100644 --- a/src/calibre/ptempfile.py +++ b/src/calibre/ptempfile.py @@ -40,7 +40,7 @@ def base_dir(): _base_dir = td else: _base_dir = tempfile.mkdtemp(prefix='%s_%s_tmp_'%(__appname__, - __version__)) + __version__), dir=os.environ.get('CALIBRE_TEMP_DIR', None)) atexit.register(remove_dir, _base_dir) return _base_dir From 89b3f22cd4d1a2544b606f369a074df70b750d8d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 30 Dec 2010 10:15:16 -0700 Subject: [PATCH 17/26] Update The Week --- .../recipes/the_week_magazine_free.recipe | 60 +++++++++---------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/resources/recipes/the_week_magazine_free.recipe b/resources/recipes/the_week_magazine_free.recipe index 1bac4133e7..6e033eaf82 100644 --- a/resources/recipes/the_week_magazine_free.recipe +++ b/resources/recipes/the_week_magazine_free.recipe @@ -1,17 +1,19 @@ - __license__ = 'GPL v3' -__copyright__ = '2010, Darko Miletic ' +__copyright__ = '2010, JOlo' ''' www.theweek.com ''' from calibre.web.feeds.news import BasicNewsRecipe +import re -class TheWeekFree(BasicNewsRecipe): - title = 'The Week Magazine - Free content' - __author__ = 'Darko Miletic' +class TheWeek(BasicNewsRecipe): + title = 'The Week Magazine' + __author__ = 'Jim Olo' description = "The best of the US and international media. Daily coverage of commentary and analysis of the day's events, as well as arts, entertainment, people and gossip, and political cartoons." publisher = 'The Week Publications, Inc.' + masthead_url = 'http://test.theweek.com/images/logo_theweek.gif' + cover_url = masthead_url category = 'news, politics, USA' oldest_article = 7 max_articles_per_feed = 100 @@ -19,31 +21,27 @@ class TheWeekFree(BasicNewsRecipe): encoding = 'utf-8' use_embedded_content = False language = 'en' + preprocess_regexps = [(re.compile(r'

', re.DOTALL), lambda match: '')] + remove_tags_before = dict(name='h1') + remove_tags_after = dict(name='div', attrs={'class':'articleSubscribe4free'}) + remove_tags = [ + dict(name='div', attrs={'class':['floatLeft','imageCaption','slideshowImageAttribution','postDate','utilities','cartoonInfo','left','middle','col300','articleSubscribe4free',' articleFlyout','articleFlyout floatRight','fourFreeBar']}) + ,dict(name='div', attrs={'id':['cartoonThumbs','rightColumn','header','partners']}) + ,dict(name='ul', attrs={'class':['slideshowNav','hotTopicsList topicList']}) + ] + remove_attributes = ['width','height', 'style', 'font', 'color'] + extra_css = ''' + h1{font-family:Geneva, Arial, Helvetica, sans-serif;color:#154B7A;} + h3{font-size: 14px;color:#999999; font-family:Geneva, Arial, Helvetica, sans-serif;font-weight: bold;} + h2{color:#666666; font-family:Geneva, Arial, Helvetica, sans-serif;font-size:small;} + p {font-family:Arial,Helvetica,sans-serif;} + ''' + filter_regexps = [r'www\.palmcoastdata\.com'] - conversion_options = { - 'comment' : description - , 'tags' : category - , 'publisher' : publisher - , 'language' : language - } - - keep_only_tags = [ - dict(name=['h1','h2']) - , dict(name='div', attrs={'class':'basefont'}) - , dict(name='div', attrs={'id':'slideshowLoader'}) - ] - - remove_tags = [ - dict(name='div', attrs={'id':['digg_dugg','articleRight','dateHeader']}) - ,dict(name=['object','embed','iframe']) - ] - - - feeds = [ - (u'News & Opinions' , u'http://www.theweek.com/section/index/news_opinion.rss') - ,(u'Arts & Leisure' , u'http://www.theweek.com/section/index/arts_leisure.rss') - ,(u'Business' , u'http://www.theweek.com/section/index/business.rss' ) - ,(u'Cartoon & Short takes' , u'http://www.theweek.com/section/index/cartoons_wit.rss') - ] - + feeds = [ + (u'News-Opinion', u'http://theweek.com/section/index/news_opinion.rss'), + (u'Business', u'http://theweek.com/section/index/business.rss'), + (u'Arts-Life', u'http://theweek.com/section/index/arts_life.rss'), + (u'Cartoons', u'http://theweek.com/section/index/cartoon_wit/0/all-cartoons.rss') + ] From 6147d566b0ce01efe46a7e9f8dcd9181d0997dcf Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 30 Dec 2010 10:16:41 -0700 Subject: [PATCH 18/26] Updated Salon --- resources/recipes/salon.recipe | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/resources/recipes/salon.recipe b/resources/recipes/salon.recipe index ed7ec98f10..c421ab094d 100644 --- a/resources/recipes/salon.recipe +++ b/resources/recipes/salon.recipe @@ -25,22 +25,20 @@ class Salon_com(BasicNewsRecipe): feeds = [ ('News & Politics', 'http://feeds.salon.com/salon/news'), - ('War Room', 'http://feeds.salon.com/salon/war_room'), - ('Arts & Entertainment', 'http://feeds.salon.com/salon/ent'), - ('I Like to Watch', 'http://feeds.salon.com/salon/iltw'), - ('Beyond Multiplex', 'http://feeds.salon.com/salon/btm'), - ('Book Reviews', 'http://feeds.salon.com/salon/books'), - ('All Life', 'http://feeds.salon.com/salon/mwt'), - ('All Opinion', 'http://feeds.salon.com/salon/opinion'), - ('Glenn Greenwald', 'http://feeds.salon.com/salon/greenwald'), - ('Garrison Keillor', 'http://dir.salon.com/topics/garrison_keillor/index.rss'), - ('Joan Walsh', 'http://www.salon.com/rss/walsh.rss'), - ('All Sports', 'http://feeds.salon.com/salon/sports'), + ('War Room', 'http://feeds.feedburner.com/salon/war_room'), + ('Joan Walsh', 'http://feeds.feedburner.com/Salon_Joan_Walsh'), + ('Glenn Greenwald', 'http://feeds.feedburner.com/salon/greenwald'), ('Tech & Business', 'http://feeds.salon.com/salon/tech'), - ('How World Works', 'http://feeds.salon.com/salon/htww') + ('Ask the Pilot', 'http://feeds.feedburner.com/salon/ask_the_pilot'), + ('How World Works', 'http://feeds.feedburner.com/salon/htww'), + ('Life', 'http://feeds.feedburner.com/salon/mwt'), + ('Broadsheet', 'http://feeds.feedburner.com/salon/broadsheet'), + ('Movie Reviews', 'http://feeds.feedburner.com/salon/movie_reviews'), + ('Film Salon', 'http://feeds.feedburner.com/Salon/Film_Salon'), + ('TV', 'http://feeds.feedburner.com/salon/tv'), + ('Books', 'http://feeds.feedburner.com/salon/books') ] def print_version(self, url): return url.replace('/index.html', '/print.html') - From a2b2364c1c4dda3508b1bec1fb696befe2213ec0 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 30 Dec 2010 10:35:30 -0700 Subject: [PATCH 19/26] Fix #8103 (Driver for Pocketbook 903) --- src/calibre/devices/eb600/driver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/calibre/devices/eb600/driver.py b/src/calibre/devices/eb600/driver.py index de8455e595..3201229699 100644 --- a/src/calibre/devices/eb600/driver.py +++ b/src/calibre/devices/eb600/driver.py @@ -230,7 +230,7 @@ class POCKETBOOK301(USBMS): class POCKETBOOK602(USBMS): name = 'PocketBook Pro 602/902 Device Interface' - description = _('Communicate with the PocketBook 602/603/902 reader.') + description = _('Communicate with the PocketBook 602/603/902/903 reader.') author = 'Kovid Goyal' supported_platforms = ['windows', 'osx', 'linux'] FORMATS = ['epub', 'fb2', 'prc', 'mobi', 'pdf', 'djvu', 'rtf', 'chm', @@ -244,7 +244,7 @@ class POCKETBOOK602(USBMS): BCD = [0x0324] VENDOR_NAME = '' - WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = ['PB602', 'PB603', 'PB902'] + WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = ['PB602', 'PB603', 'PB902', 'PB903'] class POCKETBOOK701(USBMS): From cadbd6ba5488b5fd92eba597ac7d63dd40e6be92 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 30 Dec 2010 12:01:35 -0700 Subject: [PATCH 20/26] Fix #8115 (Unsupported encoding Windows-1251) --- src/calibre/ebooks/fb2/input.py | 3 +++ src/calibre/ebooks/metadata/fb2.py | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/calibre/ebooks/fb2/input.py b/src/calibre/ebooks/fb2/input.py index 2b08a716cc..1f9a3ffe95 100644 --- a/src/calibre/ebooks/fb2/input.py +++ b/src/calibre/ebooks/fb2/input.py @@ -41,9 +41,12 @@ class FB2Input(InputFormatPlugin): from calibre.ebooks.metadata.opf2 import OPFCreator from calibre.ebooks.metadata.meta import get_metadata from calibre.ebooks.oeb.base import XLINK_NS, XHTML_NS, RECOVER_PARSER + from calibre.ebooks.chardet import xml_to_unicode NAMESPACES = {'f':FB2NS, 'l':XLINK_NS} log.debug('Parsing XML...') raw = stream.read().replace('\0', '') + raw = xml_to_unicode(raw, strip_encoding_pats=True, + assume_utf8=True)[0] try: doc = etree.fromstring(raw) except etree.XMLSyntaxError: diff --git a/src/calibre/ebooks/metadata/fb2.py b/src/calibre/ebooks/metadata/fb2.py index 3636b89df4..2d6192f949 100644 --- a/src/calibre/ebooks/metadata/fb2.py +++ b/src/calibre/ebooks/metadata/fb2.py @@ -9,6 +9,7 @@ import mimetypes, os from base64 import b64decode from lxml import etree from calibre.ebooks.metadata import MetaInformation +from calibre.ebooks.chardet import xml_to_unicode XLINK_NS = 'http://www.w3.org/1999/xlink' def XLINK(name): @@ -23,7 +24,10 @@ def get_metadata(stream): tostring = lambda x : etree.tostring(x, method='text', encoding=unicode).strip() parser = etree.XMLParser(recover=True, no_network=True) - root = etree.fromstring(stream.read(), parser=parser) + raw = stream.read() + raw = xml_to_unicode(raw, strip_encoding_pats=True, + assume_utf8=True)[0] + root = etree.fromstring(raw, parser=parser) authors, author_sort = [], None for au in XPath('//fb2:author')(root): fname = lname = author = None From 42f790e8e5eac08920bcefbd789511a5922e69d0 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 30 Dec 2010 17:26:45 -0700 Subject: [PATCH 21/26] Karlsruhe News by tfeld --- resources/recipes/karlsruhe.recipe | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 resources/recipes/karlsruhe.recipe diff --git a/resources/recipes/karlsruhe.recipe b/resources/recipes/karlsruhe.recipe new file mode 100644 index 0000000000..c0bc5369f1 --- /dev/null +++ b/resources/recipes/karlsruhe.recipe @@ -0,0 +1,52 @@ +import re +from calibre.web.feeds.news import BasicNewsRecipe + +class KANewsRecipe(BasicNewsRecipe): + title = u'KA-News.de' + description = u'Nachrichten aus Karlsruhe, Deutschland und der Welt.' + __author__ = 'tfeld' + lang='de' + no_stylesheets = True + + oldest_article = 7 + max_articles_per_feed = 100 + + feeds = [ + (u'News aus Karlsruhe', 'http://www.ka-news.de/storage/rss/rss/karlsruhe.xml'), + (u'Kulturnachrichten aus Karlsruhe', 'http://www.ka-news.de/storage/rss/rss/kultur.xml'), + (u'Durlach: News aus Durlach', 'http://www.ka-news.de/storage/rss/rss/durlach.xml'), + (u'Stutensee: News aus Stutensee Blankenloch, Büchig, Friedrichstal, Staffort, Spöck', 'http://www.ka-news.de/storage/rss/rss/stutensee.xml'), + (u'Bruchsal: News aus Bruchsal', 'http://www.ka-news.de/storage/rss/rss/bruchsal.xml'), + (u'Wirtschaftsnews aus Karlsruhe', 'http://www.ka-news.de/storage/rss/rss/wirtschaft.xml'), + (u'ka-news.de - Sport', 'http://www.ka-news.de/storage/rss/rss/sport.xml'), + (u'KSC-News - News rund um den KSC', 'http://www.ka-news.de/storage/rss/rss/ksc.xml'), + (u'ka-news.de - BG Karlsruhe', 'http://www.ka-news.de/storage/rss/rss/basketball.xml') + ] + + preprocess_regexps = [ + (re.compile(r'width:[0-9]*?px', re.DOTALL|re.IGNORECASE), lambda match: ''), + ] + + remove_tags_before = dict(id='artdetail_ueberschrift') + remove_tags_after = dict(id='artdetail_unterzeile') + remove_tags = [dict(name=['div'], attrs={'class': 'lbx_table'}), + dict(name=['div'], attrs={'class': 'lk_zumthema'}), + dict(name=['div'], attrs={'class': 'lk_thumb'}), + dict(name=['div'], attrs={'class': 'lk_trenner'}), + dict(name=['div'], attrs={'class': 'lupen_container'}), + dict(name=['script']), + dict(name=['span'], attrs={'style': 'display:none;'}), + dict(name=['span'], attrs={'class': 'comm_info'}), + dict(name=['h3'], attrs={'id': 'artdetail_unterzeile'})] + + # removing style attribute _after_ removing specifig tags above + remove_attributes = ['width','height','style'] + + extra_css = ''' + h1{ font-size:large; font-weight:bold; } + h2{ font-size:medium; font-weight:bold; } + ''' + + def get_cover_url(self): + return 'http://www.ka-news.de/storage/scl/techkanews/logos/434447_m1t1w250q75s1v29681_ka-news-Logo_mit_Schatten_transparent.png' + From df27288e8830bdc9eb517a6bf8cffc1d5c0dda92 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 30 Dec 2010 17:32:43 -0700 Subject: [PATCH 22/26] Fix #8122 (Nextbook2 or Nextbook3 Ebook Reader driver needed) --- src/calibre/customize/builtins.py | 3 ++- src/calibre/devices/misc.py | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index aea0e340c4..d0f986209c 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -478,7 +478,7 @@ from calibre.devices.teclast.driver import TECLAST_K3, NEWSMY, IPAPYRUS, \ from calibre.devices.sne.driver import SNE from calibre.devices.misc import PALMPRE, AVANT, SWEEX, PDNOVEL, KOGAN, \ GEMEI, VELOCITYMICRO, PDNOVEL_KOBO, Q600, LUMIREAD, ALURATEK_COLOR, \ - TREKSTOR, EEEREADER + TREKSTOR, EEEREADER, NEXTBOOK from calibre.devices.folder_device.driver import FOLDER_DEVICE_FOR_CONFIG from calibre.devices.kobo.driver import KOBO from calibre.devices.bambook.driver import BAMBOOK @@ -606,6 +606,7 @@ plugins += [ BAMBOOK, TREKSTOR, EEEREADER, + NEXTBOOK, ITUNES, ] plugins += [x for x in list(locals().values()) if isinstance(x, type) and \ diff --git a/src/calibre/devices/misc.py b/src/calibre/devices/misc.py index d4776ecca7..2a0fdf6433 100644 --- a/src/calibre/devices/misc.py +++ b/src/calibre/devices/misc.py @@ -264,3 +264,23 @@ class EEEREADER(USBMS): VENDOR_NAME = 'LINUX' WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = 'FILE-STOR_GADGET' +class NEXTBOOK(USBMS): + + name = 'Nextbook device interface' + gui_name = 'Nextbook' + description = _('Communicate with the Nextbook Reader') + author = 'Kovid Goyal' + supported_platforms = ['windows', 'osx', 'linux'] + + # Ordered list of supported formats + FORMATS = ['epub', 'fb2', 'txt', 'pdf'] + + VENDOR_ID = [0x05e3] + PRODUCT_ID = [0x0726] + BCD = [0x021a] + + EBOOK_DIR_MAIN = '' + + VENDOR_NAME = 'NEXT2' + WINDOWS_MAIN_MEM = '1.0.14' + From 7d3fb20c6b3745559571e0acf3052b19faef1d30 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 30 Dec 2010 22:52:04 -0700 Subject: [PATCH 23/26] Fix #8097 (Some Kindle azw books have svg code which disrupts Calibre viewer) --- src/calibre/ebooks/mobi/reader.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/calibre/ebooks/mobi/reader.py b/src/calibre/ebooks/mobi/reader.py index 02abc51cd3..14e3ed11c3 100644 --- a/src/calibre/ebooks/mobi/reader.py +++ b/src/calibre/ebooks/mobi/reader.py @@ -513,11 +513,14 @@ class MobiReader(object): mobi_version = self.book_header.mobi_version for x in root.xpath('//ncx'): x.getparent().remove(x) + svg_tags = [] for i, tag in enumerate(root.iter(etree.Element)): tag.attrib.pop('xmlns', '') for x in tag.attrib: if ':' in x: del tag.attrib[x] + if tag.tag and barename(tag.tag) == 'svg': + svg_tags.append(tag) if tag.tag and barename(tag.tag.lower()) in \ ('country-region', 'place', 'placetype', 'placename', 'state', 'city', 'street', 'address', 'content', 'form'): @@ -628,6 +631,11 @@ class MobiReader(object): cls = cls + (' ' if cls else '') + ncls attrib['class'] = cls + for tag in svg_tags: + p = tag.getparent() + if hasattr(p, 'remove'): + p.remove(tag) + def create_opf(self, htmlfile, guide=None, root=None): mi = getattr(self.book_header.exth, 'mi', self.embedded_mi) if mi is None: From 31a9f2369af525a29577600ee26d2a846d7b542b Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 30 Dec 2010 22:53:27 -0700 Subject: [PATCH 24/26] Fix #8085 (Please add support for Samsung Tab) --- src/calibre/devices/android/driver.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/calibre/devices/android/driver.py b/src/calibre/devices/android/driver.py index ced6a45da4..6387b48857 100644 --- a/src/calibre/devices/android/driver.py +++ b/src/calibre/devices/android/driver.py @@ -64,7 +64,8 @@ class ANDROID(USBMS): WINDOWS_MAIN_MEM = ['ANDROID_PHONE', 'A855', 'A853', 'INC.NEXUS_ONE', '__UMS_COMPOSITE', '_MB200', 'MASS_STORAGE', '_-_CARD', 'SGH-I897', 'GT-I9000', 'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', - 'SCH-I500_CARD', 'SPH-D700_CARD', 'MB810', 'GT-P1000', 'DESIRE'] + 'SCH-I500_CARD', 'SPH-D700_CARD', 'MB810', 'GT-P1000', 'DESIRE', + 'SGH-T849'] WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897', 'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD'] From 373176c91260aa7f3535b72c8953707260963e74 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 30 Dec 2010 22:57:51 -0700 Subject: [PATCH 25/26] Fix #7929 (Samsung Galaxy tab) --- src/calibre/customize/profiles.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/calibre/customize/profiles.py b/src/calibre/customize/profiles.py index 54c4259678..abfd6f67ce 100644 --- a/src/calibre/customize/profiles.py +++ b/src/calibre/customize/profiles.py @@ -439,6 +439,13 @@ class TabletOutput(iPadOutput): screen_size = (sys.maxint, sys.maxint) comic_screen_size = (sys.maxint, sys.maxint) +class SamsungGalaxy(TabletOutput): + name = 'Samsung Galaxy' + shortname = 'galaxy' + description = _('Intended for the Samsung Galaxy and similar tablet devices with ' + 'a resolution of 600x1280') + screen_size = comic_screen_size = (600, 1280) + class SonyReaderOutput(OutputProfile): name = 'Sony Reader' From 2e1d63816f6ca20b2171a92c333f258a4f089bd1 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 30 Dec 2010 22:58:42 -0700 Subject: [PATCH 26/26] ... --- src/calibre/customize/profiles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/customize/profiles.py b/src/calibre/customize/profiles.py index abfd6f67ce..177f482aa6 100644 --- a/src/calibre/customize/profiles.py +++ b/src/calibre/customize/profiles.py @@ -714,7 +714,7 @@ class BambookOutput(OutputProfile): output_profiles = [OutputProfile, SonyReaderOutput, SonyReader300Output, SonyReader900Output, MSReaderOutput, MobipocketOutput, HanlinV3Output, HanlinV5Output, CybookG3Output, CybookOpusOutput, KindleOutput, - iPadOutput, KoboReaderOutput, TabletOutput, + iPadOutput, KoboReaderOutput, TabletOutput, SamsungGalaxy, SonyReaderLandscapeOutput, KindleDXOutput, IlliadOutput, IRexDR1000Output, IRexDR800Output, JetBook5Output, NookOutput, BambookOutput, NookColorOutput]