From 7a466b28257f2d5080510308d939379a957724ac Mon Sep 17 00:00:00 2001 From: John Schember Date: Wed, 20 Apr 2011 21:51:49 -0400 Subject: [PATCH] Store: Format support. --- src/calibre/gui2/store/amazon_plugin.py | 1 + .../gui2/store/baen_webscription_plugin.py | 1 + src/calibre/gui2/store/bewrite_plugin.py | 15 +++++++++++++++ src/calibre/gui2/store/bn_plugin.py | 1 + src/calibre/gui2/store/diesel_ebooks_plugin.py | 3 +++ src/calibre/gui2/store/ebooks_com_plugin.py | 9 +++++++++ src/calibre/gui2/store/eharlequin_plugin.py | 1 + src/calibre/gui2/store/search.py | 16 ++++++++++++---- 8 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/calibre/gui2/store/amazon_plugin.py b/src/calibre/gui2/store/amazon_plugin.py index 2fc5f8ba1e..fe9d9c81c6 100644 --- a/src/calibre/gui2/store/amazon_plugin.py +++ b/src/calibre/gui2/store/amazon_plugin.py @@ -168,6 +168,7 @@ class AmazonKindleStore(StorePlugin): s.author = author.strip() s.price = price.strip() s.detail_item = asin.strip() + s.formats = 'Kindle' yield s diff --git a/src/calibre/gui2/store/baen_webscription_plugin.py b/src/calibre/gui2/store/baen_webscription_plugin.py index 34ccc8f917..d4f7924851 100644 --- a/src/calibre/gui2/store/baen_webscription_plugin.py +++ b/src/calibre/gui2/store/baen_webscription_plugin.py @@ -86,5 +86,6 @@ class BaenWebScriptionStore(BasicStoreConfig, StorePlugin): s.price = price s.detail_item = id.strip() s.drm = SearchResult.DRM_UNLOCKED + s.formats = 'RB, MOBI, EPUB, LIT, LRF, RTF, HTML' yield s diff --git a/src/calibre/gui2/store/bewrite_plugin.py b/src/calibre/gui2/store/bewrite_plugin.py index 1f1cc59224..716e147bbc 100644 --- a/src/calibre/gui2/store/bewrite_plugin.py +++ b/src/calibre/gui2/store/bewrite_plugin.py @@ -77,10 +77,25 @@ class BeWriteStore(BasicStoreConfig, StorePlugin): with closing(br.open(search_result.detail_item, timeout=timeout)) as nf: idata = html.fromstring(nf.read()) + price = ''.join(idata.xpath('//div[@id="content"]//td[contains(text(), "ePub")]/text()')) + if not price: + price = ''.join(idata.xpath('//div[@id="content"]//td[contains(text(), "MOBI")]/text()')) + if not price: + price = ''.join(idata.xpath('//div[@id="content"]//td[contains(text(), "PDF")]/text()')) price = '$' + price.split('$')[-1] search_result.price = price.strip() + cover_img = idata.xpath('//div[@id="content"]//img[1]/@src') if cover_img: cover_url = 'http://www.bewrite.net/mm5/' + cover_img[0] search_result.cover_url = cover_url.strip() + + formats = set([]) + if idata.xpath('boolean(//div[@id="content"]//td[contains(text(), "ePub")])'): + formats.add('EPUB') + if idata.xpath('boolean(//div[@id="content"]//td[contains(text(), "PDF")])'): + formats.add('PDF') + if idata.xpath('boolean(//div[@id="content"]//td[contains(text(), "MOBI")])'): + formats.add('MOBI') + search_result.formats = ', '.join(list(formats)) diff --git a/src/calibre/gui2/store/bn_plugin.py b/src/calibre/gui2/store/bn_plugin.py index aa74eebf54..8b1cfa03f0 100644 --- a/src/calibre/gui2/store/bn_plugin.py +++ b/src/calibre/gui2/store/bn_plugin.py @@ -79,5 +79,6 @@ class BNStore(BasicStoreConfig, StorePlugin): s.price = price s.detail_item = id.strip() s.drm = SearchResult.DRM_UNKNOWN + s.formats = 'Nook' yield s diff --git a/src/calibre/gui2/store/diesel_ebooks_plugin.py b/src/calibre/gui2/store/diesel_ebooks_plugin.py index 93edfce272..9cea376341 100644 --- a/src/calibre/gui2/store/diesel_ebooks_plugin.py +++ b/src/calibre/gui2/store/diesel_ebooks_plugin.py @@ -75,6 +75,8 @@ class DieselEbooksStore(BasicStoreConfig, StorePlugin): if price_elem: price = price_elem[0] + formats = ', '.join(data.xpath('.//td[@class="format"]/text()')) + counter -= 1 s = SearchResult() @@ -83,6 +85,7 @@ class DieselEbooksStore(BasicStoreConfig, StorePlugin): s.author = author.strip() s.price = price.strip() s.detail_item = '/item/' + id.strip() + s.formats = formats yield s diff --git a/src/calibre/gui2/store/ebooks_com_plugin.py b/src/calibre/gui2/store/ebooks_com_plugin.py index 1405b2f33e..2c3b3311c4 100644 --- a/src/calibre/gui2/store/ebooks_com_plugin.py +++ b/src/calibre/gui2/store/ebooks_com_plugin.py @@ -98,12 +98,21 @@ class EbookscomStore(BasicStoreConfig, StorePlugin): br = browser() with closing(br.open(url + id, timeout=timeout)) as nf: pdoc = html.fromstring(nf.read()) + pdata = pdoc.xpath('//table[@class="price"]/tr/td/text()') if len(pdata) >= 2: price = pdata[1] + search_result.drm = SearchResult.DRM_UNLOCKED for sec in ('Printing', 'Copying', 'Lending'): if pdoc.xpath('boolean(//div[@class="formatTableInner"]//table//tr[contains(th, "%s") and contains(td, "Off")])' % sec): search_result.drm = SearchResult.DRM_LOCKED break + + fdata = ', '.join(pdoc.xpath('//table[@class="price"]//tr//td[1]/text()')) + fdata = fdata.replace(':', '') + fdata = re.sub(r'\s{2,}', ' ', fdata) + fdata = fdata.strip() + search_result.formats = fdata + search_result.price = price.strip() diff --git a/src/calibre/gui2/store/eharlequin_plugin.py b/src/calibre/gui2/store/eharlequin_plugin.py index e77e6f11ce..325cb2f237 100644 --- a/src/calibre/gui2/store/eharlequin_plugin.py +++ b/src/calibre/gui2/store/eharlequin_plugin.py @@ -77,6 +77,7 @@ class EHarlequinStore(BasicStoreConfig, StorePlugin): s.author = author.strip() s.price = price.strip() s.detail_item = '?url=http://ebooks.eharlequin.com/' + id.strip() + s.formats = 'EPUB' yield s diff --git a/src/calibre/gui2/store/search.py b/src/calibre/gui2/store/search.py index 3c5d54afcf..506e3d4d11 100644 --- a/src/calibre/gui2/store/search.py +++ b/src/calibre/gui2/store/search.py @@ -418,12 +418,11 @@ class DetailsThread(Thread): callback(result) self.tasks.task_done() except: - traceback.print_exc() continue class Matches(QAbstractItemModel): - HEADERS = [_('Cover'), _('Title'), _('Author(s)'), _('Price'), _('DRM'), _('Store')] + HEADERS = [_('Cover'), _('Title'), _('Author(s)'), _('Price'), _('DRM'), _('Store'), _('Formats')] def __init__(self): QAbstractItemModel.__init__(self) @@ -539,6 +538,8 @@ class Matches(QAbstractItemModel): return QVariant(result.price) elif col == 5: return QVariant(result.store_name) + elif col == 6: + return QVariant(result.formats) return NONE elif role == Qt.DecorationRole: if col == 0 and result.cover_data: @@ -573,6 +574,8 @@ class Matches(QAbstractItemModel): text = 'c' elif col == 5: text = result.store_name + elif col == 6: + text = ', '.join(sorted(result.formats.split(','))) return text def sort(self, col, order, reset=True): @@ -598,6 +601,8 @@ class SearchFilter(SearchQueryParser): 'authors', 'cover', 'drm', + 'format', + 'formats', 'price', 'title', 'store', @@ -643,7 +648,7 @@ class SearchFilter(SearchQueryParser): 'author': lambda x: x.author.lower(), 'cover': lambda x: x.cover_url, 'drm': lambda x: x.drm, - 'format': '', + 'format': lambda x: x.formats, 'price': lambda x: comparable_price(x.price), 'store': lambda x: x.store_name.lower(), 'title': lambda x: x.title.lower(), @@ -681,7 +686,10 @@ class SearchFilter(SearchQueryParser): else: m = matchkind - vals = [accessor(sr)] + if locvalue == 'format': + vals = accessor(sr).split(',') + else: + vals = [accessor(sr)] if _match(query, vals, m): matches.add(sr) break