From f30784352f644e4a8d12282720d5a3862907c8c0 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 12 May 2010 13:42:13 -0600 Subject: [PATCH 01/18] Ansa and Punto Informatico by Gabriele Marini --- resources/recipes/Ansa.recipe | 72 ++++++++++++++++++++++ resources/recipes/punto_informatico.recipe | 38 ++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 resources/recipes/Ansa.recipe create mode 100644 resources/recipes/punto_informatico.recipe diff --git a/resources/recipes/Ansa.recipe b/resources/recipes/Ansa.recipe new file mode 100644 index 0000000000..8ee4cc32a7 --- /dev/null +++ b/resources/recipes/Ansa.recipe @@ -0,0 +1,72 @@ +#!/usr/bin/env python +__license__ = 'GPL v3' +__author__ = 'Gabriele Marini, based on Darko Miletic' +__copyright__ = '2010, Darko Miletic ' +description = 'Italian daily newspaper - 01-05-2010' +''' +http://www.ansa.it/ +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class Ansa(BasicNewsRecipe): + __author__ = 'Gabriele Marini' + description = 'Italian News Agency' + + cover_url = 'http://www.ansa.it/web/images/logo_ansa_interna.gif' + title = u'Ansa' + publisher = 'Ansa' + category = 'News, politics, culture, economy, general interest' + + language = 'it' + timefmt = '[%a, %d %b, %Y]' + + oldest_article = 1 + max_articles_per_feed = 10 + use_embedded_content = False + recursion = 10 + + remove_javascript = True + no_stylesheets = True + conversion_options = {'linearize_tables':True} + remove_attributes = ['colspan'] + + keep_only_tags = [dict(name='div', attrs={'class':['path','header-content','corpo']}), + ] + + + remove_tags = [ + dict(name='div', attrs={'class':'tools-bar'}), + dict(name='div', attrs={'id':['rssdiv','blocco']}) + ] + + + feeds = [ + (u'HomePage', u'http://www.ansa.it/web/ansait_web_rss_homepage.xml'), + (u'Top New', u'http://www.ansa.it/web/notizie/rubriche/topnews/topnews_rss.xml'), + (u'Cronaca', u'http://www.ansa.it/web/notizie/rubriche/cronaca/cronaca_rss.xml'), + (u'Mondo', u'http://www.ansa.it/web/notizie/rubriche/mondo/mondo_rss.xml'), + (u'Economia', u'http://www.ansa.it/web/notizie/rubriche/economia/economia_rss.xml'), + (u'Politica', u'http://www.ansa.it/web/notizie/rubriche/politica/politica_rss.xml'), + (u'Scienze', u'http://www.ansa.it/web/notizie/rubriche/scienza/scienza_rss.xml'), + (u'Cinema', u'http://www.ansa.it/web/notizie/rubriche/cinema/cinema_rss.xml'), + (u'Tecnologia e Internet', u'http://www.ansa.it/web/notizie/rubriche/tecnologia/tecnologia_rss.xml'), + (u'Spettacolo', u'http://www.ansa.it/web/notizie/rubriche/spettacolo/spettacolo_rss.xml'), + (u'Cultura e Tendenze', u'http://www.ansa.it/web/notizie/rubriche/cultura/cultura_rss.xml'), + (u'Sport', u'http://www.ansa.it/web/notizie/rubriche/altrisport/altrisport_rss.xml'), + (u'Calcio', u'http://www.ansa.it/web/notizie/rubriche/calcio/calcio_rss.xml'), + (u'Lazio', u'http://www.ansa.it/web/notizie/regioni/lazio/lazio_rss.xml'), + (u'Lombardia', u'http://www.ansa.it/web/notizie/regioni/lombardia/lombardia.shtml'), + (u'Veneto', u'http://www.ansa.it/web/notizie/regioni/veneto/veneto.shtml'), + (u'Campanioa', u'http://www.ansa.it/web/notizie/regioni/campania/campania.shtml'), + (u'Sicilia', u'http://www.ansa.it/web/notizie/regioni/sicilia/sicilia.shtml'), + (u'Toscana', u'http://www.ansa.it/web/notizie/regioni/toscana/toscana.shtml'), + (u'Trentino', u'http://www.ansa.it/web/notizie/regioni/trentino/trentino.shtml') + ] + + extra_css = ''' + .path{font-style: italic; font-size: small} + .header-content h1{font-weight: bold; font-size: xx-large} + .header-content h2{font-weight: bold; font-size: x-large; font-syle: italic} + .content-corpo{font-size: 14px;font-family: Times New Roman;} + ''' diff --git a/resources/recipes/punto_informatico.recipe b/resources/recipes/punto_informatico.recipe new file mode 100644 index 0000000000..3553d3341f --- /dev/null +++ b/resources/recipes/punto_informatico.recipe @@ -0,0 +1,38 @@ +#!/usr/bin/env python +__license__ = 'GPL v3' +__author__ = 'Gabriele Marini' +__copyright__ = 'Gabriele Marini' +__description__ = 'Punto Informatico' + +''' +http://www.punto-informatico.it/ +''' + +from calibre.web.feeds.news import BasicNewsRecipe + + +class PuntoInformatico(BasicNewsRecipe): + __author__ = 'Gabriele Marini' + description = 'Punto Informatico: Internet dal 1996' + + cover_url = 'http://punto-informatico.it/images/logo_8bit.png' + title = u'Punto Informatico ' + publisher = 'italiaNews High Tech' + category = 'News, Information Tecnology' + + language = 'it' + timefmt = '[%a, %d %b, %Y]' + + oldest_article = 15 + max_articles_per_feed = 50 + use_embedded_content = False + + remove_javascript = True + no_stylesheets = True + keep_only_tags = [dict(name='div', attrs={'class':'box'})] + remove_tags = [dict(name='div',attrs={'class':'boxadv'})] + def get_article_url(self, article): + return article.get('id', article.get('guid', None)) + + feeds = [(u'Punto Informatico',u'http://feeds.punto-informatico.it/c/32288/f/438866/index.rss')] + From 5ac40fe90ae765b4d875c152ce69942856847382 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 12 May 2010 15:20:57 -0600 Subject: [PATCH 02/18] Fix Physics World --- resources/recipes/physics_world.recipe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/recipes/physics_world.recipe b/resources/recipes/physics_world.recipe index 24e40cce78..0e3f408f6a 100644 --- a/resources/recipes/physics_world.recipe +++ b/resources/recipes/physics_world.recipe @@ -27,7 +27,7 @@ class PhysicsWorld(BasicNewsRecipe): br = BasicNewsRecipe.get_browser(self) if self.username is not None and self.password is not None: br.open('http://physicsworld.com/cws/sign-in') - br.select_form(nr=1) + br.select_form(nr=2) br['username'] = self.username br['password'] = self.password br.submit() From 4d553171b83cfbcf91d70e33d1d82080ca3eb474 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 13 May 2010 07:42:00 -0600 Subject: [PATCH 03/18] ... --- resources/recipes/physics_world.recipe | 1 + src/calibre/devices/misc.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/resources/recipes/physics_world.recipe b/resources/recipes/physics_world.recipe index 0e3f408f6a..87425e2b54 100644 --- a/resources/recipes/physics_world.recipe +++ b/resources/recipes/physics_world.recipe @@ -10,6 +10,7 @@ class PhysicsWorld(BasicNewsRecipe): oldest_article = 7 max_articles_per_feed = 100 no_stylesheets = True + cover_url = 'http://images.iop.org/cws/icons/themes/phw/header-logo.png' use_embedded_content = False remove_javascript = True needs_subscription = True diff --git a/src/calibre/devices/misc.py b/src/calibre/devices/misc.py index a375df5694..c1a2ee66da 100644 --- a/src/calibre/devices/misc.py +++ b/src/calibre/devices/misc.py @@ -66,5 +66,6 @@ class AVANT(USBMS): VENDOR_NAME = 'E-BOOK' WINDOWS_MAIN_MEM = 'READER' - EBOOK_DIR_MAIN = 'E-books' + EBOOK_DIR_MAIN = '' + SUPPORTS_SUB_DIRS = True From 5318d7305635a689b0e3973f0678d27776a0eaf1 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 13 May 2010 10:41:47 -0600 Subject: [PATCH 04/18] Add Booq to welcome wizard --- src/calibre/gui2/wizard/__init__.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/calibre/gui2/wizard/__init__.py b/src/calibre/gui2/wizard/__init__.py index 30127b7266..0a395e9eb8 100644 --- a/src/calibre/gui2/wizard/__init__.py +++ b/src/calibre/gui2/wizard/__init__.py @@ -97,9 +97,18 @@ class Kobo(Device): manufacturer = 'Kobo' output_profile = 'kobo' output_format = 'EPUB' - name = 'Kobo Reader' id = 'kobo' +class Booq(Device): + name = 'Booq Reader' + manufacturer = 'Booq' + output_profile = 'prs505' + output_format = 'EPUB' + id = 'booq' + +class Avant(Booq): + name = 'Booq Avant' + class Sony300(Sony505): name = 'SONY Reader Pocket Edition' From 0c18cf92e3f86ba9b2c138402ad2cb5e7e3cbf32 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 13 May 2010 12:38:19 -0600 Subject: [PATCH 05/18] Fix #5516 (search forward AND backward in Ebook Viewer) --- src/calibre/ebooks/oeb/iterator.py | 4 ++-- src/calibre/gui2/search_box.py | 7 +++++++ src/calibre/gui2/viewer/documentview.py | 4 +++- src/calibre/gui2/viewer/main.py | 17 ++++++++++------- src/calibre/gui2/viewer/main.ui | 22 ++++++++++++++++++++++ 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/calibre/ebooks/oeb/iterator.py b/src/calibre/ebooks/oeb/iterator.py index ed0ca6c3f4..69f7b7fe4e 100644 --- a/src/calibre/ebooks/oeb/iterator.py +++ b/src/calibre/ebooks/oeb/iterator.py @@ -92,10 +92,10 @@ class EbookIterator(object): ext = re.sub(r'(x{0,1})htm(l{0,1})', 'html', ext) self.ebook_ext = ext - def search(self, text, index): + def search(self, text, index, backwards=False): text = text.lower() for i, path in enumerate(self.spine): - if i > index: + if (backwards and i < index) or (not backwards and i > index): if text in open(path, 'rb').read().decode(path.encoding).lower(): return i diff --git a/src/calibre/gui2/search_box.py b/src/calibre/gui2/search_box.py index 033b43954a..ac86007c7f 100644 --- a/src/calibre/gui2/search_box.py +++ b/src/calibre/gui2/search_box.py @@ -137,6 +137,13 @@ class SearchBox2(QComboBox): if event.timerId() == self.timer: self.do_search() + @property + def smart_text(self): + text = unicode(self.currentText()).strip() + if not text or text == self.help_text: + return '' + return text + def do_search(self): text = unicode(self.currentText()).strip() if not text or text == self.help_text: diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py index 2267efb893..bd4bd0a01a 100644 --- a/src/calibre/gui2/viewer/documentview.py +++ b/src/calibre/gui2/viewer/documentview.py @@ -585,7 +585,9 @@ class DocumentView(QWebView): def fset(self, val): self.document.current_language = val return property(fget=fget, fset=fset) - def search(self, text): + def search(self, text, backwards=False): + if backwards: + return self.findText(text, self.document.FindBackwards) return self.findText(text) def path(self): diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index 689613111e..77d7269e17 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -229,7 +229,11 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.connect(self.action_previous_page, SIGNAL('triggered(bool)'), lambda x:self.view.previous_page()) self.connect(self.action_find_next, SIGNAL('triggered(bool)'), - lambda x:self.find(unicode(self.search.text()), True, repeat=True)) + lambda x:self.find(self.search.smart_text, True, repeat=True)) + self.connect(self.action_find_previous, SIGNAL('triggered(bool)'), + lambda x:self.find(self.search.smart_text, True, + repeat=True, backwards=True)) + self.connect(self.action_full_screen, SIGNAL('triggered(bool)'), self.toggle_fullscreen) self.action_full_screen.setShortcuts([Qt.Key_F11, Qt.CTRL+Qt.SHIFT+Qt.Key_F]) @@ -420,13 +424,15 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.set_bookmarks(self.iterator.bookmarks) - def find(self, text, refinement, repeat=False): + def find(self, text, refinement, repeat=False, backwards=False): if not text: + self.view.search('') return self.search.search_done(False) if self.view.search(text): self.scrolled(self.view.scroll_fraction) return self.search.search_done(True) - index = self.iterator.search(text, self.current_index) + index = self.iterator.search(text, self.current_index, + backwards=backwards) if index is None: if self.current_index > 0: index = self.iterator.search(text, 0) @@ -444,10 +450,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.scrolled(self.view.scroll_fraction) def keyPressEvent(self, event): - if event.key() == Qt.Key_F3: - text = unicode(self.search.text()) - self.find(text, True, repeat=True) - elif event.key() == Qt.Key_Slash: + if event.key() == Qt.Key_Slash: self.search.setFocus(Qt.OtherFocusReason) else: return MainWindow.keyPressEvent(self, event) diff --git a/src/calibre/gui2/viewer/main.ui b/src/calibre/gui2/viewer/main.ui index be18a3036b..9177f2713f 100644 --- a/src/calibre/gui2/viewer/main.ui +++ b/src/calibre/gui2/viewer/main.ui @@ -142,6 +142,7 @@ false + @@ -232,6 +233,12 @@ Find next + + Find next occurrence + + + F3 + @@ -287,6 +294,21 @@ Print + + + + :/images/arrow-up.svg:/images/arrow-up.svg + + + Find previous + + + Find previous occurrence + + + Shift+F3 + + From c3a77d4fab719b6c28bb9de6531dfae3af6c65dc Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 14 May 2010 09:29:39 -0600 Subject: [PATCH 06/18] APCOM and Leggo (it) by Marini Gabriele --- resources/recipes/apcom.recipe | 48 ++++++++++++++++++++++++++++++ resources/recipes/leggo_it.recipe | 49 +++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 resources/recipes/apcom.recipe create mode 100644 resources/recipes/leggo_it.recipe diff --git a/resources/recipes/apcom.recipe b/resources/recipes/apcom.recipe new file mode 100644 index 0000000000..9131810dd8 --- /dev/null +++ b/resources/recipes/apcom.recipe @@ -0,0 +1,48 @@ +#!/usr/bin/env python +__license__ = 'GPL v3' +__author__ = 'Gabriele Marini, based on Darko Miletic' +__copyright__ = '2009-2010, Darko Miletic ' +description = 'Italian daily newspaper - 14-05-2010' + +''' +http://www.apcom.NET/ +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class Apcom(BasicNewsRecipe): + __author__ = 'Marini Gabriele' + description = 'Italian daily newspaper' + + cover_url = 'http://www.apcom.net/img/logoAP.gif' + title = u'Apcom' + publisher = 'TM News S.p.A.' + category = 'News, politics, culture, economy, general interest' + + language = 'it' + timefmt = '[%a, %d %b, %Y]' + + oldest_article = 7 + max_articles_per_feed = 50 + use_embedded_content = False + recursion = 100 + + no_stylesheets = True + conversion_options = {'linearize_tables':True} + remove_javascript = True + + keep_only_tags = [ + dict(name='div', attrs={'id':'ag_center'}) + ] + + + + feeds = [ + (u'Globale', u'http://www.apcom.net/rss/globale.xml '), + (u'Politica', u'http://www.apcom.net/rss/politica.xml'), + (u'Cronaca', u'http://www.apcom.net/rss/cronaca.xml'), + (u'Econimia', u'http://www.apcom.net/rss/economia.xml'), + (u'Esteri', u'http://www.apcom.net/rss/esteri.xml'), + (u'Cultura', u'http://www.apcom.net/rss/cultura.xml'), + (u'Sport', u'http://www.apcom.net/rss/sport.xml') + ] diff --git a/resources/recipes/leggo_it.recipe b/resources/recipes/leggo_it.recipe new file mode 100644 index 0000000000..1e2b5aca5b --- /dev/null +++ b/resources/recipes/leggo_it.recipe @@ -0,0 +1,49 @@ +#!/usr/bin/env python +__license__ = 'GPL v3' +__author__ = 'Gabriele Marini, based on Darko Miletic' +__copyright__ = '2009, Darko Miletic ' +description = 'Italian daily newspaper - v1.00 05-05-2010' + +''' +http://www.leggo.it +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class LeggoIT(BasicNewsRecipe): + __author__ = 'Gabriele Marini' + description = 'Italian Free daily newspaper' + + cover_url = 'http://www.leggo.it/img/logo-leggo2.gif' + title = u'Leggo.it' + publisher = 'Ced Caltagirone Editore S.p.A.' + category = 'News, politics, culture, economy, general interest' + + language = 'it' + timefmt = '[%a, %d %b, %Y]' + + oldest_article = 5 + max_articles_per_feed = 100 + use_embedded_content = False + recursion = 100 + + no_stylesheets = True + remove_javascript = True + conversion_options = {'linearize_tables':True} + + keep_only_tags = [ + dict(name='h1',attrs={'class':'nero22'}), + dict(name='div',attrs={'id':'testodim'}) + ] + feeds = [ + (u'Home Page', u'http://www.leggo.it/rss/home.xml'), + (u'Italia', u'http://www.leggo.it/rss/italia.xml'), + (u'Esteri', u'http://www.leggo.it/rss/esteri.xml'), + (u'Economia', u'http://www.leggo.it/rss/economia.xml'), + (u'Sport', u'http://www.leggo.it/rss/sport.xml'), + (u'Gossip', u'http://www.leggo.it/rss/gossip.xml'), + (u'Spettacoli', u'http://www.leggo.it/rss/spettacoli.xml'), + (u'Salute', u'http://www.leggo.it/rss/salute.xml'), + (u'Scienza', u'http://www.leggo.it/rss/scienza.xml') + ] + From 93013855050f06245fee2eb9ce3969e04703e8f0 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 14 May 2010 21:44:30 -0600 Subject: [PATCH 07/18] Fix bug that caused send to device to send ultiple copies to the device if you used Prefrences --- src/calibre/gui2/ui.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 99ab5470dc..ab5edd3964 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -396,6 +396,9 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): self.action_sync.setShortcut(Qt.Key_D) self.action_sync.setEnabled(True) self.create_device_menu() + self.connect(self.action_sync, SIGNAL('triggered(bool)'), + self._sync_action_triggered) + self.action_edit.setMenu(md) self.action_save.setMenu(self.save_menu) @@ -641,6 +644,10 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): MainWindow.resizeEvent(self, ev) self.search.setMaximumWidth(self.width()-150) + def _sync_action_triggered(self, *args): + m = getattr(self, '_sync_menu', None) + if m is not None: + m.trigger_default() def create_device_menu(self): self._sync_menu = DeviceMenu(self) @@ -648,8 +655,6 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): self.connect(self._sync_menu, SIGNAL('sync(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'), self.dispatch_sync_event) - self.connect(self.action_sync, SIGNAL('triggered(bool)'), - self._sync_menu.trigger_default) self._sync_menu.fetch_annotations.connect(self.fetch_annotations) def add_spare_server(self, *args): From a96002fa1bc9580ebc9323cb1c9fdfa745a34693 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 15 May 2010 09:24:19 -0600 Subject: [PATCH 08/18] Fix #5525 ("The Nation" recipe not working) --- resources/recipes/the_nation.recipe | 51 +++++++++++++++-------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/resources/recipes/the_nation.recipe b/resources/recipes/the_nation.recipe index 2a1f226e56..0e4d8d83ef 100644 --- a/resources/recipes/the_nation.recipe +++ b/resources/recipes/the_nation.recipe @@ -1,37 +1,40 @@ -#!/usr/bin/env python - __license__ = 'GPL v3' -__copyright__ = '2008, Darko Miletic ' +__copyright__ = '2008 - 2010, Darko Miletic ' ''' thenation.com ''' from calibre.web.feeds.news import BasicNewsRecipe class Thenation(BasicNewsRecipe): - title = u'The Nation' - __author__ = u'Darko Miletic' - description = u'Unconventional Wisdom Since 1865' + title = 'The Nation' + __author__ = 'Darko Miletic' + description = 'Unconventional Wisdom Since 1865' + publisher = 'The Nation' + category = 'news, politics, USA' oldest_article = 120 + encoding = 'utf-8' max_articles_per_feed = 100 no_stylesheets = True - language = 'en' - - use_embedded_content = False - simultaneous_downloads = 1 + language = 'en' + use_embedded_content = False delay = 1 - timefmt = ' [%A, %d %B, %Y]' - + masthead_url = 'http://www.thenation.com/sites/default/themes/thenation/images/logo-main.gif' + exra_css = ' body{font-family: Arial,Helvetica,sans-serif;} .print-created{font-size: small;} .caption{display: block; font-size: x-small;} ' - keep_only_tags = [ dict(name='div', attrs={'class':'main'}) ] - remove_tags = [ - dict(name='div', attrs={'class':'mod tools'}) - ,dict(name='div', attrs={'class':'inset' }) - ,dict(name='div', attrs={'class':'share' }) - ,dict(name='ol' , attrs={'id' :'comments' }) - ,dict(name='p' , attrs={'class':'info' }) - ,dict(name='a' , attrs={'class':'comments' }) - ,dict(name='ul' , attrs={'class':'important'}) - ,dict(name='object') - ] + conversion_options = { + 'comment' : description + , 'tags' : category + , 'publisher' : publisher + , 'language' : language + } - feeds = [(u"Top Stories", u'http://feedproxy.google.com/TheNationEdPicks')] + keep_only_tags = [ dict(attrs={'class':['print-title','print-created','print-content','print-links']}) ] + remove_tags = [dict(name='link')] + + feeds = [(u"Editor's Picks", u'http://www.thenation.com/rss/editors_picks')] + + def print_version(self, url): + return url.replace('.thenation.com/','.thenation.com/print/') + + def preprocess_html(self, soup): + return self.adeify_images(soup) From b7421bc3caf42e88125d31365cefc37e277dff98 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 15 May 2010 09:55:29 -0600 Subject: [PATCH 09/18] ... --- src/calibre/devices/hanvon/driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/devices/hanvon/driver.py b/src/calibre/devices/hanvon/driver.py index 463dc69079..aa384910cd 100644 --- a/src/calibre/devices/hanvon/driver.py +++ b/src/calibre/devices/hanvon/driver.py @@ -24,7 +24,7 @@ class N516(USBMS): VENDOR_ID = [0x0525] PRODUCT_ID = [0xa4a5] - BCD = [0x323, 0x326] + BCD = [0x323, 0x326, 0x399] VENDOR_NAME = 'INGENIC' WINDOWS_MAIN_MEM = '_FILE-STOR_GADGE' From de305d2d950f6ffc088bb9f2b26e9299045fb604 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 15 May 2010 10:14:29 -0600 Subject: [PATCH 10/18] EPUB Input: Fix typo that caused incorrect processing of EPUB files with more than one identifier element and encrypted fonts --- src/calibre/ebooks/epub/input.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/calibre/ebooks/epub/input.py b/src/calibre/ebooks/epub/input.py index 48699521c7..0f94fb674a 100644 --- a/src/calibre/ebooks/epub/input.py +++ b/src/calibre/ebooks/epub/input.py @@ -32,9 +32,9 @@ class EPUBInput(InputFormatPlugin): key = None for item in opf.identifier_iter(): scheme = None - for key in item.attrib.keys(): - if key.endswith('scheme'): - scheme = item.get(key) + for xkey in item.attrib.keys(): + if xkey.endswith('scheme'): + scheme = item.get(xkey) if (scheme and scheme.lower() == 'uuid') or \ (item.text and item.text.startswith('urn:uuid:')): key = str(item.text).rpartition(':')[-1] From d866fcc48f076c3f9c639b68d114015507059e16 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 15 May 2010 10:29:21 -0600 Subject: [PATCH 11/18] Fix #5501 (Error after query of social metadata if ISBN not find) --- src/calibre/ebooks/metadata/amazon.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/calibre/ebooks/metadata/amazon.py b/src/calibre/ebooks/metadata/amazon.py index d1473be8f0..1713d044f5 100644 --- a/src/calibre/ebooks/metadata/amazon.py +++ b/src/calibre/ebooks/metadata/amazon.py @@ -19,12 +19,18 @@ AWS_NS = 'http://webservices.amazon.com/AWSECommerceService/2005-10-05' def AWS(tag): return '{%s}%s'%(AWS_NS, tag) -def check_for_errors(root): +class ISBNNotFound(ValueError): + pass + +def check_for_errors(root, isbn): err = root.find('.//'+AWS('Error')) if err is not None: + text = etree.tostring(err, method='text', pretty_print=True, + encoding=unicode) + if 'AWS.InvalidParameterValue'+isbn in text: + raise ISBNNotFound(isbn) raise Exception('Failed to get metadata with error: '\ - + etree.tostring(err, method='text', pretty_print=True, - encoding=unicode)) + + text) def get_social_metadata(title, authors, publisher, isbn): mi = MetaInformation(title, authors) @@ -32,7 +38,10 @@ def get_social_metadata(title, authors, publisher, isbn): br = browser() response_xml = br.open('http://status.calibre-ebook.com/aws/metadata/'+isbn).read() root = etree.fromstring(response_xml) - check_for_errors(root) + try: + check_for_errors(root, isbn) + except ISBNNotFound: + return mi mi.title = root.findtext('.//'+AWS('Title')) authors = [x.text for x in root.findall('.//'+AWS('Author'))] if authors: From b8af81da1077d1cb08239a10bd4daecc4f0a2d58 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 15 May 2010 10:54:10 -0600 Subject: [PATCH 12/18] Improve the Christian Science Monitor --- resources/recipes/chr_mon.recipe | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/resources/recipes/chr_mon.recipe b/resources/recipes/chr_mon.recipe index 79c991efa8..2b431ebd0b 100644 --- a/resources/recipes/chr_mon.recipe +++ b/resources/recipes/chr_mon.recipe @@ -37,6 +37,7 @@ class ChristianScienceMonitor(BasicNewsRecipe): preprocess_regexps = [ (re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in [ + (r'', lambda match : ''), (r'
.*?
', lambda m: ''), (r'Full HTML version of this story which may include photos, graphics, and related links.*', @@ -79,7 +80,10 @@ class ChristianScienceMonitor(BasicNewsRecipe): remove_tags = [ dict(name='div', attrs={'id':['story-tools','videoPlayer','storyRelatedBottom','enlarge-photo','photo-paginate']}), - dict(name='div', attrs={'class':['storyToolbar cfx','podStoryRel','spacer3','divvy spacer7','comment','storyIncludeBottom']}), + dict(name=['div','a'], attrs={'class': + ['storyToolbar cfx','podStoryRel','spacer3', + 'divvy spacer7','comment','storyIncludeBottom', + 'hide', 'podBrdr']}), dict(name='ul', attrs={'class':[ 'centerliststories']}) , dict(name='form', attrs={'id':[ 'commentform']}) , ] From 421475f02a696d2fb1cd07d399d74e64becda777 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 15 May 2010 10:58:00 -0600 Subject: [PATCH 13/18] Fix #5503 (Add an icon for the RTF file format) --- src/calibre/gui2/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 94f969d7e9..4c75758567 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -339,6 +339,7 @@ class FileIconProvider(QFileIconProvider): 'tan' : 'zero', 'epub' : 'epub', 'fb2' : 'fb2', + 'rtf' : 'rtf', } def __init__(self): From 56e2918c1311f02647a2ddc2a38f1edbab2268b5 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 15 May 2010 12:24:10 -0600 Subject: [PATCH 14/18] calibredb: Add ability to create empty books in the database. Fixes #5504 (Improve bulk creation of empty book items) --- src/calibre/library/cli.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py index 7f2c4ab926..12b7944383 100644 --- a/src/calibre/library/cli.py +++ b/src/calibre/library/cli.py @@ -376,12 +376,35 @@ the directory related options below. help=_('Process directories recursively')) parser.add_option('-d', '--duplicates', action='store_true', default=False, help=_('Add books to database even if they already exist. Comparison is done based on book titles.')) + parser.add_option('-e', '--empty', action='store_true', default=False, + help=_('Add an empty book (a book with no formats)')) + parser.add_option('-t', '--title', default=None, + help=_('Set the title of the added empty book')) + parser.add_option('-a', '--authors', default=None, + help=_('Set the authors of the added empty book')) + parser.add_option('-i', '--isbn', default=None, + help=_('Set the ISBN of the added empty book')) + return parser +def do_add_empty(db, title, authors, isbn): + from calibre.ebooks.metadata import MetaInformation, string_to_authors + mi = MetaInformation(None) + if title is not None: + mi.title = title + if authors: + mi.authors = string_to_authors(authors) + if isbn: + mi.isbn = isbn + db.import_book(mi, []) + send_message() def command_add(args, dbpath): parser = add_option_parser() opts, args = parser.parse_args(sys.argv[:1] + args) + if opts.empty: + do_add_empty(get_db(dbpath, opts), opts.title, opts.authors, opts.isbn) + return 0 if len(args) < 2: parser.print_help() print From eabd4dc9b57f23e7c5b1f9971ba23dfc410c27a8 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 15 May 2010 19:18:36 -0600 Subject: [PATCH 15/18] ... --- resources/recipes/the_escapist.recipe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/recipes/the_escapist.recipe b/resources/recipes/the_escapist.recipe index 6ff8debe53..5730dd2858 100644 --- a/resources/recipes/the_escapist.recipe +++ b/resources/recipes/the_escapist.recipe @@ -15,7 +15,7 @@ class al(BasicNewsRecipe): description = 'The Escapist Magazine' cover_url = 'http://cdn.themis-media.com/themes/escapistmagazine/default/images/logo.png' - title = u'the Escapist Magazine' + title = u'The Escapist Magazine' publisher = 'Themis media' category = 'Video games news, lifestyle, gaming culture' From d7a9c4884941340384736e92785eeeffa1eec01f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 15 May 2010 19:32:52 -0600 Subject: [PATCH 16/18] Fix #5500 (adding duplicate books creates temporary blank line at bottom of book list) --- src/calibre/gui2/add.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/gui2/add.py b/src/calibre/gui2/add.py index 3f9d1925b5..becf78e85f 100644 --- a/src/calibre/gui2/add.py +++ b/src/calibre/gui2/add.py @@ -199,11 +199,11 @@ class DBAdder(Thread): self.add_formats(id, formats) else: id = self.db.create_book_entry(mi, cover=cover, add_duplicates=False) - self.number_of_books_added += 1 if id is None: self.duplicates.append((mi, cover, orig_formats)) else: self.add_formats(id, formats) + self.number_of_books_added += 1 else: self.names.append(name) self.paths.append(formats[0]) From 561f7a2c68c179cbde915962953a33bd715caacc Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 15 May 2010 20:43:21 -0600 Subject: [PATCH 17/18] Fix #5518 (EPUB: Unable to clear or delete series and update file series meta data when saving to disk) --- src/calibre/customize/__init__.py | 4 ++++ src/calibre/customize/builtins.py | 2 +- src/calibre/customize/ui.py | 13 +++++++++++++ src/calibre/ebooks/metadata/epub.py | 10 +++++++++- src/calibre/ebooks/metadata/opf2.py | 9 +++++++++ src/calibre/ebooks/metadata/worker.py | 4 +++- 6 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/calibre/customize/__init__.py b/src/calibre/customize/__init__.py index 0d6f041736..4eaaf3b90a 100644 --- a/src/calibre/customize/__init__.py +++ b/src/calibre/customize/__init__.py @@ -236,6 +236,10 @@ class MetadataWriterPlugin(Plugin): type = _('Metadata writer') + def __init__(self, *args, **kwargs): + Plugin.__init__(self, *args, **kwargs) + self.apply_null = False + def set_metadata(self, stream, mi, type): ''' Set metadata for the file represented by stream (a file like object diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index e9dd3d0cb4..52ec8fa255 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -329,7 +329,7 @@ class EPUBMetadataWriter(MetadataWriterPlugin): def set_metadata(self, stream, mi, type): from calibre.ebooks.metadata.epub import set_metadata - set_metadata(stream, mi) + set_metadata(stream, mi, apply_null=self.apply_null) class LRFMetadataWriter(MetadataWriterPlugin): diff --git a/src/calibre/customize/ui.py b/src/calibre/customize/ui.py index 68c26386c9..a2521b0023 100644 --- a/src/calibre/customize/ui.py +++ b/src/calibre/customize/ui.py @@ -187,6 +187,18 @@ class QuickMetadata(object): quick_metadata = QuickMetadata() +class ApplyNullMetadata(object): + + def __init__(self): + self.apply_null = False + + def __enter__(self): + self.apply_null = True + + def __exit__(self, *args): + self.apply_null = False + +apply_null_metadata = ApplyNullMetadata() def get_file_type_metadata(stream, ftype): mi = MetaInformation(None, None) @@ -214,6 +226,7 @@ def set_file_type_metadata(stream, mi, ftype): if not is_disabled(plugin): with plugin: try: + plugin.apply_null = apply_null_metadata.apply_null plugin.set_metadata(stream, mi, ftype.lower().strip()) break except: diff --git a/src/calibre/ebooks/metadata/epub.py b/src/calibre/ebooks/metadata/epub.py index 1dab9cd91c..d74ed37f66 100644 --- a/src/calibre/ebooks/metadata/epub.py +++ b/src/calibre/ebooks/metadata/epub.py @@ -182,13 +182,21 @@ def get_metadata(stream, extract_cover=True): def get_quick_metadata(stream): return get_metadata(stream, False) -def set_metadata(stream, mi): +def set_metadata(stream, mi, apply_null=False): stream.seek(0) reader = OCFZipReader(stream, root=os.getcwdu()) mi = MetaInformation(mi) for x in ('guide', 'toc', 'manifest', 'spine'): setattr(mi, x, None) reader.opf.smart_update(mi) + if apply_null: + if not getattr(mi, 'series', None): + reader.opf.series = None + if not getattr(mi, 'tags', []): + reader.opf.tags = [] + if not getattr(mi, 'isbn', None): + reader.opf.isbn = None + newopf = StringIO(reader.opf.render()) safe_replace(stream, reader.container[OPF.MIMETYPE], newopf) diff --git a/src/calibre/ebooks/metadata/opf2.py b/src/calibre/ebooks/metadata/opf2.py index 7eeac5cc85..e429574e57 100644 --- a/src/calibre/ebooks/metadata/opf2.py +++ b/src/calibre/ebooks/metadata/opf2.py @@ -404,6 +404,10 @@ class MetadataField(object): def __set__(self, obj, val): elem = obj.get_metadata_element(self.name) + if val is None: + if elem is not None: + elem.getparent().remove(elem) + return if elem is None: elem = obj.create_metadata_element(self.name, is_dc=self.is_dc) obj.set_text(elem, unicode(val)) @@ -722,6 +726,11 @@ class OPF(object): def fset(self, val): matches = self.isbn_path(self.metadata) + if val is None: + if matches: + for x in matches: + x.getparent().remove(x) + return if not matches: attrib = {'{%s}scheme'%self.NAMESPACES['opf']: 'ISBN'} matches = [self.create_metadata_element('identifier', diff --git a/src/calibre/ebooks/metadata/worker.py b/src/calibre/ebooks/metadata/worker.py index 3fc33f42cd..178174a0d7 100644 --- a/src/calibre/ebooks/metadata/worker.py +++ b/src/calibre/ebooks/metadata/worker.py @@ -235,6 +235,7 @@ def save_book(task, library_path, path, recs, notification=lambda x,y:x): from calibre.library.database2 import LibraryDatabase2 db = LibraryDatabase2(library_path) from calibre.library.save_to_disk import config, save_to_disk + from calibre.customize.ui import apply_null_metadata opts = config().parse() for name in recs: setattr(opts, name, recs[name]) @@ -244,5 +245,6 @@ def save_book(task, library_path, path, recs, notification=lambda x,y:x): notification((id, title, not failed, tb)) return True - save_to_disk(db, task, path, opts, callback) + with apply_null_metadata: + save_to_disk(db, task, path, opts, callback) From 70f94c6b71c25230d44e239c54fdeb17e6798daf Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 15 May 2010 21:24:56 -0600 Subject: [PATCH 18/18] version 0.6.53 --- Changelog.yaml | 81 ++++++++++++++++++++++++++++++++++++++++ src/calibre/constants.py | 2 +- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/Changelog.yaml b/Changelog.yaml index ec083af809..d6204743f8 100644 --- a/Changelog.yaml +++ b/Changelog.yaml @@ -4,6 +4,87 @@ # for important features/bug fixes. # Also, each release can have new and improved recipes. +- version: 0.6.53 + date: 2010-05-15 + + new features: + - title: "Clean up GUI initialization and add support for restoring corrupted databases automatically" + + - title: "Make proxy detection more robust on windows and OS X. calibre now queries OS X Network Settigns if no environment variables are set. Also handle proxies with a trailing slash correctly" + + - title: "Add EPUB advanced formatting demo to User Manual" + + - title: "Support for the Booq Avant, Azbooka and the Samsung GT-I5700" + + - title: "Backwards search in the E-book viewer" + + - title: "calibredb: Add ability to create empty books in the database." + tickets: [5504] + + - title: "Conversion pipeline: Support for the :first-letter pseudo selector" + + - title: "Interpret a Keyboard interrupt (Ctrl+C) as a request to quit the main GUI" + + - title: "CBC Input: Handle comics.txt encoded in UTF-16 with a BOM" + + bug fixes: + - title: "HTML Input: Fix silly bug in case sensitivity detection" + + - title: "Kobo driver: Show all sideloaded content on the device." + tickets: [5492] + + - title: "EPUB metadata: Fix bug with relative apths in encryption detection when reading cover" + tickets: [5471] + + - title: "E-book viewer: Fix next page scrolling when current document is just a little more than a screenfull. Also use a more robust method to insert blank space at the end of the document when the last screenfull is partially empty." + + - title: "EPUB metadata: Allow deletion of series/tags/isbn from EPUB files when Saving to Disk" + tickets: [5518] + + - title: "Fix regression that caused temporary blank line at the bottom of the books list when adding duplicates" + tickets: [5500] + + - title: "Add icon for RTF" + tickets: [5503] + + - title: "Amazon metadata: If ISBN is not found, don't report an error message." + tickets: [5501] + + - title: "EPUB Input: Fix typo that caused incorrect processing of EPUB files with more than one identifier element and encrypted fonts" + + - title: "Fix bug that caused send to device to send multiple copies to the device if you had previously used Prefrences" + + - title: "Linux prs 500 udev rule: Use SUBSYSTEMS instead of the deprecated BUS" + + - title: "PML2PMLZ plugin: Actually compress the PML file stored in the PMLZ archive" + tickets: [5511] + + - title: "SONY drivers: Fix regression that broke collection ordering by series when sending to device. And fix another rare error condition." + tickets: [5487] + + - title: "CHM Input: Regression that broke CHM conversion on OS X." + tickets: [5483] + + - title: "Fix PDB created in Dropbook not convertable by Calibre" + tickets: [5441] + + + new recipes: + - title: APCOM, Leggo (it), Ansa and Punto Informatico + author: Gabriele Marini + + - title: Scinexx.de + author: JSuer + + - title: Various Russian news sources + author: Darko Miletic + + improved recipes: + - Christian Science Monitor + - The Nation + - Physics World + - Discover Magazine + - version: 0.6.52 date: 2010-05-07 diff --git a/src/calibre/constants.py b/src/calibre/constants.py index b470b3c239..7e52798e65 100644 --- a/src/calibre/constants.py +++ b/src/calibre/constants.py @@ -2,7 +2,7 @@ __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __docformat__ = 'restructuredtext en' __appname__ = 'calibre' -__version__ = '0.6.52' +__version__ = '0.6.53' __author__ = "Kovid Goyal " import re