From db385fac26a541ac57f6d42c93d4d80fff47e183 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sat, 7 May 2011 15:50:07 +0100 Subject: [PATCH 01/10] First cut at beam ebooks. Also fix format names in foyles and waterstones to match other stores. --- src/calibre/customize/builtins.py | 12 ++- .../gui2/store/beam_ebooks_de_plugin.py | 89 +++++++++++++++++++ src/calibre/gui2/store/foyles_uk_plugin.py | 2 +- .../gui2/store/waterstones_uk_plugin.py | 2 +- 4 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 src/calibre/gui2/store/beam_ebooks_de_plugin.py diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index 36bcbdbfe2..ff9861c537 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -1171,13 +1171,19 @@ class StoreFoylesUKStore(StoreBase): description = _('Foyles of London, online') actual_plugin = 'calibre.gui2.store.foyles_uk_plugin:FoylesUKStore' -class AmazonDEKindleStore(StoreBase): +class StoreAmazonDEKindleStore(StoreBase): name = 'Amazon DE Kindle' description = _('Kindle eBooks') actual_plugin = 'calibre.gui2.store.amazon_de_plugin:AmazonDEKindleStore' -plugins += [StoreAmazonKindleStore, AmazonDEKindleStore, StoreAmazonUKKindleStore, - StoreBaenWebScriptionStore, StoreBNStore, +class StoreBeamEBooksDEStore(StoreBase): + name = 'Beam EBooks DE' + description = _('Kindle eBooks') + actual_plugin = 'calibre.gui2.store.beam_ebooks_de_plugin:BeamEBooksDEStore' + +plugins += [StoreAmazonKindleStore, StoreAmazonDEKindleStore, + StoreAmazonUKKindleStore, + StoreBaenWebScriptionStore, StoreBNStore, StoreBeamEBooksDEStore, StoreBeWriteStore, StoreDieselEbooksStore, StoreEbookscomStore, StoreEHarlequinStoretore, StoreFeedbooksStore, StoreFoylesUKStore, StoreGutenbergStore, StoreKoboStore, StoreManyBooksStore, diff --git a/src/calibre/gui2/store/beam_ebooks_de_plugin.py b/src/calibre/gui2/store/beam_ebooks_de_plugin.py new file mode 100644 index 0000000000..18cff7a411 --- /dev/null +++ b/src/calibre/gui2/store/beam_ebooks_de_plugin.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- + +from __future__ import (unicode_literals, division, absolute_import, print_function) + +__license__ = 'GPL 3' +__copyright__ = '2011, John Schember ' +__docformat__ = 'restructuredtext en' + +import urllib2 +from contextlib import closing + +from lxml import html + +from PyQt4.Qt import QUrl + +from calibre import browser +from calibre.gui2 import open_url +from calibre.gui2.store import StorePlugin +from calibre.gui2.store.basic_config import BasicStoreConfig +from calibre.gui2.store.search_result import SearchResult +from calibre.gui2.store.web_store_dialog import WebStoreDialog + +class BeamEBooksDEStore(BasicStoreConfig, StorePlugin): + + def open(self, parent=None, detail_item=None, external=False): + url = 'http://www.beam-ebooks.de' + url_details = 'http://www.beam-ebooks.de{0}' + + if external or self.config.get('open_external', False): + if detail_item: + url = url_details.format(detail_item) + open_url(QUrl(url)) + else: + detail_url = None + if detail_item: + detail_url = url_details.format(detail_item) + d = WebStoreDialog(self.gui, url, parent, detail_url) + d.setWindowTitle(self.name) + d.set_tags(self.config.get('tags', '')) + d.exec_() + + def search(self, query, max_results=10, timeout=60): + url = 'http://www.beam-ebooks.de/suchergebnis.php?Type=&sw=' + urllib2.quote(query) + print(url) + br = browser() + + counter = max_results + with closing(br.open(url, timeout=timeout)) as f: + doc = html.fromstring(f.read()) + print(doc) + for data in doc.xpath('//table[tr/td/div[@class="stil2"]]'): + print('here1') + if counter <= 0: + break + + id = ''.join(data.xpath('./tr/td/div[@class="stil2"]/a/@href')).strip() + print('here', id) + if not id: + continue + cover_url = ''.join(data.xpath('./tr/td[1]/a/img/@src')) + if cover_url: + cover_url = 'http://www.beam-ebooks.de' + cover_url + title = ''.join(data.xpath('./tr/td/div[@class="stil2"]/a/b/text()')) + author = ' '.join(data.xpath('./tr/td/div[@class="stil2"]/child::b/text()|./tr/td/div[@class="stil2"]/child::strong/text()')) + price = ''.join(data.xpath('./tr/td[3]/text()')) + print(data.xpath('./tr/td[3]/a/img/@alt')) + pdf = data.xpath('boolean(./tr/td[3]/a/img[contains(@alt, "PDF")]/@alt)') + epub = data.xpath('boolean(./tr/td[3]/a/img[contains(@alt, "ePub")]/@alt)') + mobi = data.xpath('boolean(./tr/td[3]/a/img[contains(@alt, "Mobipocket")]/@alt)') + print(id, cover_url, title, author, price, pdf, epub, mobi) + counter -= 1 + + s = SearchResult() + s.cover_url = cover_url + s.title = title.strip() + s.author = author.strip() + s.price = price + s.drm = SearchResult.DRM_UNLOCKED + s.detail_item = id + formats = [] + if epub: + formats.append('ePub') + if pdf: + formats.append('PDF') + if mobi: + formats.append('MOBI') + s.formats = ', '.join(formats) + + yield s diff --git a/src/calibre/gui2/store/foyles_uk_plugin.py b/src/calibre/gui2/store/foyles_uk_plugin.py index ca35fb6bb2..1a997cd671 100644 --- a/src/calibre/gui2/store/foyles_uk_plugin.py +++ b/src/calibre/gui2/store/foyles_uk_plugin.py @@ -73,6 +73,6 @@ class FoylesUKStore(BasicStoreConfig, StorePlugin): s.price = price s.detail_item = id s.drm = SearchResult.DRM_LOCKED - s.formats = 'EPUB' + s.formats = 'ePub' yield s diff --git a/src/calibre/gui2/store/waterstones_uk_plugin.py b/src/calibre/gui2/store/waterstones_uk_plugin.py index d422165c47..a5065128ba 100644 --- a/src/calibre/gui2/store/waterstones_uk_plugin.py +++ b/src/calibre/gui2/store/waterstones_uk_plugin.py @@ -76,7 +76,7 @@ class WaterstonesUKStore(BasicStoreConfig, StorePlugin): s.detail_item = id formats = [] if epub: - formats.append('EPUB') + formats.append('ePub') if pdf: formats.append('PDF') s.formats = ', '.join(formats) From e219f7214dca2b84b054077506867b2096298572 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Sun, 8 May 2011 13:36:08 +0100 Subject: [PATCH 02/10] Add epubbuy. Continue a bit with beam. --- src/calibre/customize/builtins.py | 11 ++- .../gui2/store/beam_ebooks_de_plugin.py | 5 +- src/calibre/gui2/store/epubbuy_de_plugin.py | 73 +++++++++++++++++++ 3 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 src/calibre/gui2/store/epubbuy_de_plugin.py diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index 7f1705e8ff..5faa2de232 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -1126,7 +1126,7 @@ class StoreEbookscomStore(StoreBase): description = _('The digital bookstore.') actual_plugin = 'calibre.gui2.store.ebooks_com_plugin:EbookscomStore' -class StoreEHarlequinStoretore(StoreBase): +class StoreEHarlequinStore(StoreBase): name = 'eHarlequin' description = _('entertain, enrich, inspire.') actual_plugin = 'calibre.gui2.store.eharlequin_plugin:EHarlequinStore' @@ -1183,14 +1183,19 @@ class StoreAmazonDEKindleStore(StoreBase): class StoreBeamEBooksDEStore(StoreBase): name = 'Beam EBooks DE' - description = _('Kindle eBooks') + description = _('der eBook Shop') actual_plugin = 'calibre.gui2.store.beam_ebooks_de_plugin:BeamEBooksDEStore' +class StoreEPubBuyDEStore(StoreBase): + name = 'EPUBBuy DE' + description = _('EPUBReaders eBook Shop') + actual_plugin = 'calibre.gui2.store.epubbuy_de_plugin:EPubBuyDEStore' + plugins += [StoreAmazonKindleStore, StoreAmazonDEKindleStore, StoreAmazonUKKindleStore, StoreBaenWebScriptionStore, StoreBNStore, StoreBeamEBooksDEStore, StoreBeWriteStore, StoreDieselEbooksStore, StoreEbookscomStore, - StoreEHarlequinStoretore, StoreFeedbooksStore, + StoreEPubBuyDEStore, StoreEHarlequinStore, StoreFeedbooksStore, StoreFoylesUKStore, StoreGutenbergStore, StoreKoboStore, StoreManyBooksStore, StoreMobileReadStore, StoreOpenLibraryStore, StoreSmashwordsStore, StoreWaterstonesUKStore] diff --git a/src/calibre/gui2/store/beam_ebooks_de_plugin.py b/src/calibre/gui2/store/beam_ebooks_de_plugin.py index 18cff7a411..d5a9d8f12c 100644 --- a/src/calibre/gui2/store/beam_ebooks_de_plugin.py +++ b/src/calibre/gui2/store/beam_ebooks_de_plugin.py @@ -23,8 +23,8 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog class BeamEBooksDEStore(BasicStoreConfig, StorePlugin): def open(self, parent=None, detail_item=None, external=False): - url = 'http://www.beam-ebooks.de' - url_details = 'http://www.beam-ebooks.de{0}' + url = 'http://www.affiliwelt.net/klick.php?log=no&prid=908&pid=2&bannerid=10072&url=http://www.beam-ebooks.de' + url_details = 'http://www.affiliwelt.net/klick.php?log=no&prid=908&pid=2&bannerid=10072&url=http://www.beam-ebooks.de{0}' if external or self.config.get('open_external', False): if detail_item: @@ -34,6 +34,7 @@ class BeamEBooksDEStore(BasicStoreConfig, StorePlugin): detail_url = None if detail_item: detail_url = url_details.format(detail_item) + print(detail_url) d = WebStoreDialog(self.gui, url, parent, detail_url) d.setWindowTitle(self.name) d.set_tags(self.config.get('tags', '')) diff --git a/src/calibre/gui2/store/epubbuy_de_plugin.py b/src/calibre/gui2/store/epubbuy_de_plugin.py new file mode 100644 index 0000000000..6b92e101f8 --- /dev/null +++ b/src/calibre/gui2/store/epubbuy_de_plugin.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- + +from __future__ import (unicode_literals, division, absolute_import, print_function) + +__license__ = 'GPL 3' +__copyright__ = '2011, John Schember ' +__docformat__ = 'restructuredtext en' + +import urllib2 +from contextlib import closing + +from lxml import html + +from PyQt4.Qt import QUrl + +from calibre import browser +from calibre.gui2 import open_url +from calibre.gui2.store import StorePlugin +from calibre.gui2.store.basic_config import BasicStoreConfig +from calibre.gui2.store.search_result import SearchResult +from calibre.gui2.store.web_store_dialog import WebStoreDialog + +class EPubBuyDEStore(BasicStoreConfig, StorePlugin): + + def open(self, parent=None, detail_item=None, external=False): + url = 'http://www.epubbuy.com/' + url_details = '{0}' + + if external or self.config.get('open_external', False): + if detail_item: + url = url_details.format(detail_item) + open_url(QUrl(url)) + else: + detail_url = None + if detail_item: + detail_url = url_details.format(detail_item) + d = WebStoreDialog(self.gui, url, parent, detail_url) + d.setWindowTitle(self.name) + d.set_tags(self.config.get('tags', '')) + d.exec_() + + def search(self, query, max_results=10, timeout=60): + url = 'http://www.epubbuy.com/search.php?search_query=' + urllib2.quote(query) + br = browser() + + counter = max_results + with closing(br.open(url, timeout=timeout)) as f: + doc = html.fromstring(f.read()) + for data in doc.xpath('//li[contains(@class, "ajax_block_product")]'): + if counter <= 0: + break + + id = ''.join(data.xpath('./div[@class="center_block"]/a[@class="product_img_link"]/@href')).strip() + if not id: + continue + cover_url = ''.join(data.xpath('./div[@class="center_block"]/a[@class="product_img_link"]/img/@src')) + if cover_url: + cover_url = 'http://www.epubbuy.com' + cover_url + title = ''.join(data.xpath('./div[@class="center_block"]/a[@class="product_img_link"]/@title')) + author = ''.join(data.xpath('./div[@class="center_block"]/a[2]/text()')) + price = ''.join(data.xpath('.//span[@class="price"]/text()')) + counter -= 1 + + s = SearchResult() + s.cover_url = cover_url + s.title = title.strip() + s.author = author.strip() + s.price = price + s.drm = SearchResult.DRM_UNLOCKED + s.detail_item = id + s.formats = 'ePub' + + yield s From fce83cea050d2af17fa5f357e6cf52ad4d989391 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Mon, 9 May 2011 08:05:21 +0100 Subject: [PATCH 03/10] Visual improvements on the alternate metadata dialogs. 1) Use a pushbutton instead of a toolbutton for config metadata download in Alt1 and Alt2 2) Add a touch of space between the left and right borders of the dialog and the buttons. --- src/calibre/gui2/metadata/single.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/calibre/gui2/metadata/single.py b/src/calibre/gui2/metadata/single.py index 84f0405fc6..6b9d786951 100644 --- a/src/calibre/gui2/metadata/single.py +++ b/src/calibre/gui2/metadata/single.py @@ -31,6 +31,7 @@ class MetadataSingleDialogBase(ResizableDialog): view_format = pyqtSignal(object, object) cc_two_column = tweaks['metadata_single_use_2_cols_for_custom_fields'] one_line_comments_toolbar = False + use_toolbutton_for_config_metadata = True def __init__(self, db, parent=None): self.db = db @@ -71,7 +72,9 @@ class MetadataSingleDialogBase(ResizableDialog): self.l.addWidget(self.scroll_area) ll = self.button_box_layout = QHBoxLayout() self.l.addLayout(ll) + ll.addSpacing(10) ll.addWidget(self.button_box) + ll.addSpacing(10) self.setWindowIcon(QIcon(I('edit_input.png'))) self.setWindowTitle(_('Edit Metadata')) @@ -191,8 +194,12 @@ class MetadataSingleDialogBase(ResizableDialog): font.setBold(True) self.fetch_metadata_button.setFont(font) - self.config_metadata_button = QToolButton(self) - self.config_metadata_button.setIcon(QIcon(I('config.png'))) + if self.use_toolbutton_for_config_metadata: + self.config_metadata_button = QToolButton(self) + self.config_metadata_button.setIcon(QIcon(I('config.png'))) + else: + self.config_metadata_button = QPushButton(self) + self.config_metadata_button.setText(_('Configure metadata downloading')) self.config_metadata_button.clicked.connect(self.configure_metadata) self.config_metadata_button.setToolTip( _('Change how calibre downloads metadata')) @@ -614,6 +621,7 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{ cc_two_column = False one_line_comments_toolbar = True + use_toolbutton_for_config_metadata = False on_drag_enter = pyqtSignal() @@ -649,10 +657,8 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{ self.tabs[0].l.addWidget(gb, 0, 0, 1, 1) gb.setLayout(tl) - self.button_box_layout.insertWidget(0, self.fetch_metadata_button) - self.config_metadata_button.setToolButtonStyle(Qt.ToolButtonTextOnly) - self.config_metadata_button.setText(_('Configure metadata downloading')) - self.button_box_layout.insertWidget(1, self.config_metadata_button) + self.button_box_layout.insertWidget(1, self.fetch_metadata_button) + self.button_box_layout.insertWidget(2, self.config_metadata_button) sto(self.button_box, self.fetch_metadata_button) sto(self.fetch_metadata_button, self.config_metadata_button) sto(self.config_metadata_button, self.title) @@ -767,6 +773,7 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{ cc_two_column = False one_line_comments_toolbar = True + use_toolbutton_for_config_metadata = False def do_layout(self): self.central_widget.clear() @@ -785,10 +792,8 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{ l.addWidget(gb, 0, 0, 1, 1) gb.setLayout(tl) - self.button_box_layout.insertWidget(0, self.fetch_metadata_button) - self.config_metadata_button.setToolButtonStyle(Qt.ToolButtonTextOnly) - self.config_metadata_button.setText(_('Configure metadata downloading')) - self.button_box_layout.insertWidget(1, self.config_metadata_button) + self.button_box_layout.insertWidget(1, self.fetch_metadata_button) + self.button_box_layout.insertWidget(2, self.config_metadata_button) sto(self.button_box, self.fetch_metadata_button) sto(self.fetch_metadata_button, self.config_metadata_button) sto(self.config_metadata_button, self.title) From 518134c195a49c7aef3789f1fd6413fadf32df63 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Mon, 9 May 2011 11:03:13 +0100 Subject: [PATCH 04/10] ... --- src/calibre/gui2/metadata/single.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/calibre/gui2/metadata/single.py b/src/calibre/gui2/metadata/single.py index 6b9d786951..5c4e241bba 100644 --- a/src/calibre/gui2/metadata/single.py +++ b/src/calibre/gui2/metadata/single.py @@ -199,7 +199,8 @@ class MetadataSingleDialogBase(ResizableDialog): self.config_metadata_button.setIcon(QIcon(I('config.png'))) else: self.config_metadata_button = QPushButton(self) - self.config_metadata_button.setText(_('Configure metadata downloading')) + self.config_metadata_button.setText(_('Configure download metadata')) + self.config_metadata_button.setIcon(QIcon(I('config.png'))) self.config_metadata_button.clicked.connect(self.configure_metadata) self.config_metadata_button.setToolTip( _('Change how calibre downloads metadata')) From 85e1100db35f9ddfaffcec619b67e6bd272c749b Mon Sep 17 00:00:00 2001 From: GRiker Date: Mon, 9 May 2011 17:44:33 -0600 Subject: [PATCH 05/10] Added support for custom icons in MessageBox --- src/calibre/gui2/dialogs/message_box.py | 27 +++++++++++++++---------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/calibre/gui2/dialogs/message_box.py b/src/calibre/gui2/dialogs/message_box.py index f9354a0cfc..fdec19dc69 100644 --- a/src/calibre/gui2/dialogs/message_box.py +++ b/src/calibre/gui2/dialogs/message_box.py @@ -19,17 +19,23 @@ class MessageBox(QDialog, Ui_Dialog): # {{{ INFO = 2 QUESTION = 3 - def __init__(self, type_, title, msg, det_msg='', show_copy_button=True, - parent=None): + def __init__(self, type_, title, msg, + det_msg='', + q_icon=None, + show_copy_button=True, + parent=None): QDialog.__init__(self, parent) - icon = { - self.ERROR : 'error', - self.WARNING: 'warning', - self.INFO: 'information', - self.QUESTION: 'question', - }[type_] - icon = 'dialog_%s.png'%icon - self.icon = QIcon(I(icon)) + if q_icon is None: + icon = { + self.ERROR : 'error', + self.WARNING: 'warning', + self.INFO: 'information', + self.QUESTION: 'question', + }[type_] + icon = 'dialog_%s.png'%icon + self.icon = QIcon(I(icon)) + else: + self.icon = q_icon self.setupUi(self) self.setWindowTitle(title) @@ -44,7 +50,6 @@ class MessageBox(QDialog, Ui_Dialog): # {{{ self.bb.ActionRole) self.ctc_button.clicked.connect(self.copy_to_clipboard) - self.show_det_msg = _('Show &details') self.hide_det_msg = _('Hide &details') self.det_msg_toggle = self.bb.addButton(self.show_det_msg, self.bb.ActionRole) From c11164f9820faef3a9eb235033e51daf7c0a6e60 Mon Sep 17 00:00:00 2001 From: GRiker Date: Mon, 9 May 2011 17:58:16 -0600 Subject: [PATCH 06/10] Added Product IDs for iPad2 (Wifi) and iPad2 (CDMA) --- src/calibre/devices/apple/driver.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/calibre/devices/apple/driver.py b/src/calibre/devices/apple/driver.py index 922afc4338..b7d5ac36d2 100644 --- a/src/calibre/devices/apple/driver.py +++ b/src/calibre/devices/apple/driver.py @@ -203,9 +203,11 @@ class ITUNES(DriverBase): # 0x1294 iPhone 3GS # 0x1297 iPhone 4 # 0x129a iPad - # 0x12a2 iPad2 + # 0x129f iPad2 (WiFi) + # 0x12a2 iPad2 (GSM) + # 0x12a3 iPad2 (CDMA) VENDOR_ID = [0x05ac] - PRODUCT_ID = [0x1292,0x1293,0x1294,0x1297,0x1299,0x129a,0x129f,0x12a2] + PRODUCT_ID = [0x1292,0x1293,0x1294,0x1297,0x1299,0x129a,0x129f,0x12a2,0x12a3] BCD = [0x01] # Plugboard ID From 778eaffa972123db37a2bba952442e94c07c296c Mon Sep 17 00:00:00 2001 From: John Schember Date: Mon, 9 May 2011 22:11:23 -0400 Subject: [PATCH 07/10] HTMLZ: Fix covers again... --- src/calibre/ebooks/htmlz/input.py | 16 ++++++++-------- src/calibre/ebooks/metadata/extz.py | 20 ++++++++------------ 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/calibre/ebooks/htmlz/input.py b/src/calibre/ebooks/htmlz/input.py index d083fcc4ab..743d8e53eb 100644 --- a/src/calibre/ebooks/htmlz/input.py +++ b/src/calibre/ebooks/htmlz/input.py @@ -7,7 +7,6 @@ __copyright__ = '2011, John Schember ' __docformat__ = 'restructuredtext en' import os -import posixpath from calibre import guess_type, walk from calibre.customize.conversion import InputFormatPlugin @@ -74,22 +73,23 @@ class HTMLZInput(InputFormatPlugin): meta_info_to_oeb_metadata(mi, oeb.metadata, log) # Get the cover path from the OPF. - cover_href = None + cover_path = None opf = None for x in walk('.'): if os.path.splitext(x)[1].lower() in ('.opf'): opf = x break if opf: - opf = OPF(opf) - cover_href = posixpath.relpath(opf.cover, os.path.dirname(stream.name)) + opf = OPF(opf, basedir=os.getcwd()) + cover_path = opf.raster_cover # Set the cover. - if cover_href: + if cover_path: cdata = None - with open(cover_href, 'rb') as cf: + with open(os.path.join(os.getcwd(), cover_path), 'rb') as cf: cdata = cf.read() - id, href = oeb.manifest.generate('cover', cover_href) - oeb.manifest.add(id, href, guess_type(cover_href)[0], data=cdata) + cover_name = os.path.basename(cover_path) + id, href = oeb.manifest.generate('cover', cover_name) + oeb.manifest.add(id, href, guess_type(cover_name)[0], data=cdata) oeb.guide.add('cover', 'Cover', href) return oeb diff --git a/src/calibre/ebooks/metadata/extz.py b/src/calibre/ebooks/metadata/extz.py index 021450fca5..f3725027a9 100644 --- a/src/calibre/ebooks/metadata/extz.py +++ b/src/calibre/ebooks/metadata/extz.py @@ -8,12 +8,11 @@ Read meta information from extZ (TXTZ, HTMLZ...) files. ''' import os -import posixpath from cStringIO import StringIO from calibre.ebooks.metadata import MetaInformation -from calibre.ebooks.metadata.opf2 import OPF, metadata_to_opf +from calibre.ebooks.metadata.opf2 import OPF from calibre.ptempfile import PersistentTemporaryFile from calibre.utils.zipfile import ZipFile, safe_replace @@ -31,9 +30,9 @@ def get_metadata(stream, extract_cover=True): opf = OPF(opf_stream) mi = opf.to_book_metadata() if extract_cover: - cover_href = posixpath.relpath(opf.cover, os.path.dirname(stream.name)) + cover_href = opf.raster_cover if cover_href: - mi.cover_data = ('jpg', zf.read(cover_href)) + mi.cover_data = (os.path.splitext(cover_href)[1], zf.read(cover_href)) except: return mi return mi @@ -59,18 +58,15 @@ def set_metadata(stream, mi): except: pass if new_cdata: - cover = opf.cover - if not cover: - cover = 'cover.jpg' - cpath = posixpath.join(posixpath.dirname(opf_path), cover) + cpath = opf.raster_cover + if not cpath: + cpath = 'cover.jpg' new_cover = _write_new_cover(new_cdata, cpath) replacements[cpath] = open(new_cover.name, 'rb') - mi.cover = cover + mi.cover = cpath # Update the metadata. - old_mi = opf.to_book_metadata() - old_mi.smart_update(mi) - opf.smart_update(metadata_to_opf(old_mi), replace_metadata=True) + opf.smart_update(mi, replace_metadata=True) newopf = StringIO(opf.render()) safe_replace(stream, opf_path, newopf, extra_replacements=replacements, add_missing=True) From 6ebdda7aa54af32316cb962f7b815a692eef7f75 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 10 May 2011 12:58:54 +0100 Subject: [PATCH 08/10] Beam store, with working links --- src/calibre/gui2/store/beam_ebooks_de_plugin.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/calibre/gui2/store/beam_ebooks_de_plugin.py b/src/calibre/gui2/store/beam_ebooks_de_plugin.py index d5a9d8f12c..385bbc5456 100644 --- a/src/calibre/gui2/store/beam_ebooks_de_plugin.py +++ b/src/calibre/gui2/store/beam_ebooks_de_plugin.py @@ -23,8 +23,8 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog class BeamEBooksDEStore(BasicStoreConfig, StorePlugin): def open(self, parent=None, detail_item=None, external=False): - url = 'http://www.affiliwelt.net/klick.php?log=no&prid=908&pid=2&bannerid=10072&url=http://www.beam-ebooks.de' - url_details = 'http://www.affiliwelt.net/klick.php?log=no&prid=908&pid=2&bannerid=10072&url=http://www.beam-ebooks.de{0}' + url = 'http://klick.affiliwelt.net/klick.php?bannerid=10072&pid=32307&prid=908' + url_details = 'http://klick.affiliwelt.net/klick.php?bannerid=10730&pid=32307&prid=908&prodid={0}' if external or self.config.get('open_external', False): if detail_item: @@ -34,7 +34,6 @@ class BeamEBooksDEStore(BasicStoreConfig, StorePlugin): detail_url = None if detail_item: detail_url = url_details.format(detail_item) - print(detail_url) d = WebStoreDialog(self.gui, url, parent, detail_url) d.setWindowTitle(self.name) d.set_tags(self.config.get('tags', '')) @@ -42,33 +41,28 @@ class BeamEBooksDEStore(BasicStoreConfig, StorePlugin): def search(self, query, max_results=10, timeout=60): url = 'http://www.beam-ebooks.de/suchergebnis.php?Type=&sw=' + urllib2.quote(query) - print(url) br = browser() counter = max_results with closing(br.open(url, timeout=timeout)) as f: doc = html.fromstring(f.read()) - print(doc) for data in doc.xpath('//table[tr/td/div[@class="stil2"]]'): - print('here1') if counter <= 0: break id = ''.join(data.xpath('./tr/td/div[@class="stil2"]/a/@href')).strip() - print('here', id) if not id: continue + id = id[7:] cover_url = ''.join(data.xpath('./tr/td[1]/a/img/@src')) if cover_url: cover_url = 'http://www.beam-ebooks.de' + cover_url title = ''.join(data.xpath('./tr/td/div[@class="stil2"]/a/b/text()')) author = ' '.join(data.xpath('./tr/td/div[@class="stil2"]/child::b/text()|./tr/td/div[@class="stil2"]/child::strong/text()')) price = ''.join(data.xpath('./tr/td[3]/text()')) - print(data.xpath('./tr/td[3]/a/img/@alt')) pdf = data.xpath('boolean(./tr/td[3]/a/img[contains(@alt, "PDF")]/@alt)') epub = data.xpath('boolean(./tr/td[3]/a/img[contains(@alt, "ePub")]/@alt)') mobi = data.xpath('boolean(./tr/td[3]/a/img[contains(@alt, "Mobipocket")]/@alt)') - print(id, cover_url, title, author, price, pdf, epub, mobi) counter -= 1 s = SearchResult() From c10349c5dd2b518cc7b6c8ab26dd102c28902a47 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 10 May 2011 15:18:16 +0100 Subject: [PATCH 09/10] Final versions of Beam and EPUBBuy. --- .../gui2/store/beam_ebooks_de_plugin.py | 19 ++++++++++++++----- src/calibre/gui2/store/epubbuy_de_plugin.py | 17 ++++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/calibre/gui2/store/beam_ebooks_de_plugin.py b/src/calibre/gui2/store/beam_ebooks_de_plugin.py index 385bbc5456..ee73607c57 100644 --- a/src/calibre/gui2/store/beam_ebooks_de_plugin.py +++ b/src/calibre/gui2/store/beam_ebooks_de_plugin.py @@ -24,7 +24,8 @@ class BeamEBooksDEStore(BasicStoreConfig, StorePlugin): def open(self, parent=None, detail_item=None, external=False): url = 'http://klick.affiliwelt.net/klick.php?bannerid=10072&pid=32307&prid=908' - url_details = 'http://klick.affiliwelt.net/klick.php?bannerid=10730&pid=32307&prid=908&prodid={0}' + url_details = ('http://klick.affiliwelt.net/klick.php?' + 'bannerid=10730&pid=32307&prid=908&prodid={0}') if external or self.config.get('open_external', False): if detail_item: @@ -54,15 +55,23 @@ class BeamEBooksDEStore(BasicStoreConfig, StorePlugin): if not id: continue id = id[7:] + print(id) cover_url = ''.join(data.xpath('./tr/td[1]/a/img/@src')) if cover_url: cover_url = 'http://www.beam-ebooks.de' + cover_url title = ''.join(data.xpath('./tr/td/div[@class="stil2"]/a/b/text()')) - author = ' '.join(data.xpath('./tr/td/div[@class="stil2"]/child::b/text()|./tr/td/div[@class="stil2"]/child::strong/text()')) + author = ' '.join(data.xpath('./tr/td/div[@class="stil2"]/' + 'child::b/text()' + '|' + './tr/td/div[@class="stil2"]/' + 'child::strong/text()')) price = ''.join(data.xpath('./tr/td[3]/text()')) - pdf = data.xpath('boolean(./tr/td[3]/a/img[contains(@alt, "PDF")]/@alt)') - epub = data.xpath('boolean(./tr/td[3]/a/img[contains(@alt, "ePub")]/@alt)') - mobi = data.xpath('boolean(./tr/td[3]/a/img[contains(@alt, "Mobipocket")]/@alt)') + pdf = data.xpath( + 'boolean(./tr/td[3]/a/img[contains(@alt, "PDF")]/@alt)') + epub = data.xpath( + 'boolean(./tr/td[3]/a/img[contains(@alt, "ePub")]/@alt)') + mobi = data.xpath( + 'boolean(./tr/td[3]/a/img[contains(@alt, "Mobipocket")]/@alt)') counter -= 1 s = SearchResult() diff --git a/src/calibre/gui2/store/epubbuy_de_plugin.py b/src/calibre/gui2/store/epubbuy_de_plugin.py index 6b92e101f8..242ef76793 100644 --- a/src/calibre/gui2/store/epubbuy_de_plugin.py +++ b/src/calibre/gui2/store/epubbuy_de_plugin.py @@ -23,8 +23,9 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog class EPubBuyDEStore(BasicStoreConfig, StorePlugin): def open(self, parent=None, detail_item=None, external=False): - url = 'http://www.epubbuy.com/' - url_details = '{0}' + url = 'http://klick.affiliwelt.net/klick.php?bannerid=47653&pid=32307&prid=2627' + url_details = ('http://klick.affiliwelt.net/klick.php?bannerid=47653' + '&pid=32307&prid=2627&prodid={0}') if external or self.config.get('open_external', False): if detail_item: @@ -50,13 +51,19 @@ class EPubBuyDEStore(BasicStoreConfig, StorePlugin): if counter <= 0: break - id = ''.join(data.xpath('./div[@class="center_block"]/a[@class="product_img_link"]/@href')).strip() + id = ''.join(data.xpath('./div[@class="center_block"]' + '/p[contains(text(), "artnr:")]/text()')).strip() if not id: continue - cover_url = ''.join(data.xpath('./div[@class="center_block"]/a[@class="product_img_link"]/img/@src')) + id = id[6:].strip() + if not id: + continue + cover_url = ''.join(data.xpath('./div[@class="center_block"]' + '/a[@class="product_img_link"]/img/@src')) if cover_url: cover_url = 'http://www.epubbuy.com' + cover_url - title = ''.join(data.xpath('./div[@class="center_block"]/a[@class="product_img_link"]/@title')) + title = ''.join(data.xpath('./div[@class="center_block"]' + '/a[@class="product_img_link"]/@title')) author = ''.join(data.xpath('./div[@class="center_block"]/a[2]/text()')) price = ''.join(data.xpath('.//span[@class="price"]/text()')) counter -= 1 From d9e0e361408aa64eecbcf683428d06c8ab10cac3 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 10 May 2011 16:18:13 +0100 Subject: [PATCH 10/10] Remove a print statement --- src/calibre/gui2/store/beam_ebooks_de_plugin.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/calibre/gui2/store/beam_ebooks_de_plugin.py b/src/calibre/gui2/store/beam_ebooks_de_plugin.py index ee73607c57..b589a8c310 100644 --- a/src/calibre/gui2/store/beam_ebooks_de_plugin.py +++ b/src/calibre/gui2/store/beam_ebooks_de_plugin.py @@ -55,7 +55,6 @@ class BeamEBooksDEStore(BasicStoreConfig, StorePlugin): if not id: continue id = id[7:] - print(id) cover_url = ''.join(data.xpath('./tr/td[1]/a/img/@src')) if cover_url: cover_url = 'http://www.beam-ebooks.de' + cover_url