From ebf4ee8fedcb571c6d82b901304c9d8822280b80 Mon Sep 17 00:00:00 2001 From: John Schember Date: Tue, 19 Apr 2011 20:32:24 -0400 Subject: [PATCH] Store: Add drm status indicators. Add DRM status results for Manybooks, amazon, baen and bwrite. --- resources/images/drm-locked.png | Bin 0 -> 1612 bytes resources/images/drm-unlocked.png | Bin 0 -> 1675 bytes src/calibre/gui2/store/amazon_plugin.py | 11 ++++ .../gui2/store/baen_webscription_plugin.py | 1 + src/calibre/gui2/store/bewrite_plugin.py | 1 + src/calibre/gui2/store/manybooks_plugin.py | 1 + src/calibre/gui2/store/search.py | 52 +++++++++++++++--- 7 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 resources/images/drm-locked.png create mode 100644 resources/images/drm-unlocked.png diff --git a/resources/images/drm-locked.png b/resources/images/drm-locked.png new file mode 100644 index 0000000000000000000000000000000000000000..84c7a5e7b1db1d4f92b896cce2a4a82e07e4de34 GIT binary patch literal 1612 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 bU(cr<`1(Q8GaR;m^~nIQJ%02W8Ykl~+{W{F literal 0 HcmV?d00001 diff --git a/src/calibre/gui2/store/amazon_plugin.py b/src/calibre/gui2/store/amazon_plugin.py index 51986ee4df..067e9e899e 100644 --- a/src/calibre/gui2/store/amazon_plugin.py +++ b/src/calibre/gui2/store/amazon_plugin.py @@ -159,6 +159,16 @@ class AmazonKindleStore(StorePlugin): author = ''.join(data.xpath('div[@class="productTitle"]/span[@class="ptBrand"]/text()')) author = author.split('by')[-1] price = ''.join(data.xpath('div[@class="newPrice"]/span/text()')) + + with closing(br.open(asin_href, timeout=timeout/4)) as nf: + idata = html.fromstring(nf.read()) + if idata.xpath('boolean(//div[@class="content"]//li/b[contains(text(), "Simultaneous Device Usage")])'): + if idata.xpath('boolean(//div[@class="content"]//li[contains(., "Unlimited") and contains(b, "Simultaneous Device Usage")])'): + drm = False + else: + drm = None + else: + drm = True counter -= 1 @@ -168,5 +178,6 @@ class AmazonKindleStore(StorePlugin): s.author = author.strip() s.price = price.strip() s.detail_item = asin.strip() + s.drm = drm yield s diff --git a/src/calibre/gui2/store/baen_webscription_plugin.py b/src/calibre/gui2/store/baen_webscription_plugin.py index 46a7c1ec7c..79b8751796 100644 --- a/src/calibre/gui2/store/baen_webscription_plugin.py +++ b/src/calibre/gui2/store/baen_webscription_plugin.py @@ -85,5 +85,6 @@ class BaenWebScriptionStore(BasicStoreConfig, StorePlugin): s.author = author.strip() s.price = price s.detail_item = id.strip() + s.drm = False yield s diff --git a/src/calibre/gui2/store/bewrite_plugin.py b/src/calibre/gui2/store/bewrite_plugin.py index 37bd9cf9a5..887390a3af 100644 --- a/src/calibre/gui2/store/bewrite_plugin.py +++ b/src/calibre/gui2/store/bewrite_plugin.py @@ -76,5 +76,6 @@ class BeWriteStore(BasicStoreConfig, StorePlugin): s.author = author.strip() s.price = price.strip() s.detail_item = id.strip() + s.drm = False yield s diff --git a/src/calibre/gui2/store/manybooks_plugin.py b/src/calibre/gui2/store/manybooks_plugin.py index 72fe54c427..697a31eb85 100644 --- a/src/calibre/gui2/store/manybooks_plugin.py +++ b/src/calibre/gui2/store/manybooks_plugin.py @@ -89,5 +89,6 @@ class ManyBooksStore(BasicStoreConfig, StorePlugin): s.author = author.strip() s.price = price.strip() s.detail_item = '/titles/' + id + s.drm = False yield s diff --git a/src/calibre/gui2/store/search.py b/src/calibre/gui2/store/search.py index c94c43537f..61e278afee 100644 --- a/src/calibre/gui2/store/search.py +++ b/src/calibre/gui2/store/search.py @@ -95,9 +95,11 @@ class SearchDialog(QDialog, Ui_Dialog): # Author self.results_view.setColumnWidth(2,int(total*.35)) # Price - self.results_view.setColumnWidth(3, int(total*.10)) + self.results_view.setColumnWidth(3, int(total*.5)) + # DRM + self.results_view.setColumnWidth(4, int(total*.5)) # Store - self.results_view.setColumnWidth(4, int(total*.20)) + self.results_view.setColumnWidth(5, int(total*.20)) def do_search(self, checked=False): # Stop all running threads. @@ -311,6 +313,7 @@ class SearchThread(Thread): self.results.put(res) self.tasks.task_done() except: + traceback.print_exc() pass def _clean_query(self, query): @@ -379,10 +382,15 @@ class CoverThread(Thread): class Matches(QAbstractItemModel): - HEADERS = [_('Cover'), _('Title'), _('Author(s)'), _('Price'), _('Store')] + HEADERS = [_('Cover'), _('Title'), _('Author(s)'), _('Price'), _('DRM'), _('Store')] def __init__(self): QAbstractItemModel.__init__(self) + + self.DRM_LOCKED_ICON = QPixmap(I('drm-locked.png')).scaledToHeight(64) + self.DRM_UNLOCKED_ICON = QPixmap(I('drm-unlocked.png')).scaledToHeight(64) + self.DRM_UNKNOWN_ICON = QPixmap(I('dialog_warning.png')).scaledToHeight(64) + self.matches = [] self.cover_pool = CoverThreadPool(CoverThread, 2) self.cover_pool.start_threads() @@ -448,7 +456,7 @@ class Matches(QAbstractItemModel): return QVariant(result.author) elif col == 3: return QVariant(result.price) - elif col == 4: + elif col == 5: return QVariant(result.store_name) return NONE elif role == Qt.DecorationRole: @@ -456,6 +464,13 @@ class Matches(QAbstractItemModel): p = QPixmap() p.loadFromData(result.cover_data) return QVariant(p) + if col == 4: + if result.drm: + return QVariant(self.DRM_LOCKED_ICON) + if result.drm == False: + return QVariant(self.DRM_UNLOCKED_ICON) + else: + return QVariant(self.DRM_UNKNOWN_ICON) elif role == Qt.SizeHintRole: return QSize(64, 64) return NONE @@ -469,6 +484,13 @@ class Matches(QAbstractItemModel): elif col == 3: text = comparable_price(result.price) elif col == 4: + if result.drm: + text = 'a' + elif result.drm == False: + text = 'b' + else: + text = 'c' + elif col == 5: text = result.store_name return text @@ -490,6 +512,7 @@ class SearchFilter(SearchQueryParser): 'author', 'authors', 'cover', + 'drm', 'price', 'title', 'store', @@ -528,7 +551,7 @@ class SearchFilter(SearchQueryParser): q = { 'author': self.search_result.author.lower(), 'cover': self.search_result.cover_url, - 'drm': '', + 'drm': self.search_result.drm, 'format': '', 'price': comparable_price(self.search_result.price), 'store': self.search_result.store_name.lower(), @@ -539,12 +562,23 @@ class SearchFilter(SearchQueryParser): for locvalue in locations: ac_val = q[locvalue] if query == 'true': - if ac_val is not None: - matches.add(self.search_result) + if locvalue == 'drm': + if ac_val == True: + matches.add(self.search_result) + else: + if ac_val is not None: + matches.add(self.search_result) continue if query == 'false': - if ac_val is None: - matches.add(self.search_result) + if locvalue == 'drm': + if ac_val == False: + matches.add(self.search_result) + else: + if ac_val is None: + matches.add(self.search_result) + continue + # this is bool, so can't match below + if locvalue == 'drm': continue try: ### Can't separate authors because comma is used for name sep and author sep