diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index b2d3a967df..ac26544207 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -1164,6 +1164,12 @@ class StoreFoylesUKStore(StoreBase): description = _('Foyles of London, online.') actual_plugin = 'calibre.gui2.store.foyles_uk_plugin:FoylesUKStore' +class StoreGandalfStore(StoreBase): + name = 'Gandalf' + author = 'Tomasz Długosz' + description = _('Zaczarowany świat książek') + actual_plugin = 'calibre.gui2.store.gandalf_plugin:GandalfStore' + class StoreGoogleBooksStore(StoreBase): name = 'Google Books' description = _('Google Books') @@ -1191,6 +1197,7 @@ class StoreMobileReadStore(StoreBase): class StoreNextoStore(StoreBase): name = 'Nexto' + author = 'Tomasz Długosz' description = _('Audiobooki mp3, ebooki, prasa - księgarnia internetowa.') actual_plugin = 'calibre.gui2.store.nexto_plugin:NextoStore' @@ -1204,6 +1211,11 @@ class StoreOReillyStore(StoreBase): description = _('DRM-Free tech ebooks.') actual_plugin = 'calibre.gui2.store.oreilly_plugin:OReillyStore' +class StorePragmaticBookshelfStore(StoreBase): + name = 'Pragmatic Bookshelf' + description = _('The Pragmatic Bookshelf') + actual_plugin = 'calibre.gui2.store.pragmatic_bookshelf_plugin:PragmaticBookshelfStore' + class StoreSmashwordsStore(StoreBase): name = 'Smashwords' description = _('Your ebook. Your way.') @@ -1224,15 +1236,35 @@ class StoreWizardsTowerBooksStore(StoreBase): description = 'Wizard\'s Tower Press.' actual_plugin = 'calibre.gui2.store.wizards_tower_books_plugin:WizardsTowerBooksStore' -plugins += [StoreArchiveOrgStore, StoreAmazonKindleStore, StoreAmazonDEKindleStore, - StoreAmazonUKKindleStore, StoreBaenWebScriptionStore, StoreBNStore, - StoreBeamEBooksDEStore, StoreBeWriteStore, - StoreDieselEbooksStore, StoreEbookscomStore, StoreEPubBuyDEStore, - StoreEHarlequinStore, StoreFeedbooksStore, - StoreFoylesUKStore, StoreGoogleBooksStore, StoreGutenbergStore, - StoreKoboStore, StoreManyBooksStore, - StoreMobileReadStore, StoreNextoStore, StoreOpenLibraryStore, - StoreOReillyStore, StoreSmashwordsStore, - StoreWaterstonesUKStore, StoreWeightlessBooksStore, StoreWizardsTowerBooksStore] +plugins += [ + StoreArchiveOrgStore, + StoreAmazonKindleStore, + StoreAmazonDEKindleStore, + StoreAmazonUKKindleStore, + StoreBaenWebScriptionStore, + StoreBNStore, + StoreBeamEBooksDEStore, + StoreBeWriteStore, + StoreDieselEbooksStore, + StoreEbookscomStore, + StoreEPubBuyDEStore, + StoreEHarlequinStore, + StoreFeedbooksStore, + StoreFoylesUKStore, + StoreGandalfStore, + StoreGoogleBooksStore, + StoreGutenbergStore, + StoreKoboStore, + StoreManyBooksStore, + StoreMobileReadStore, + StoreNextoStore, + StoreOpenLibraryStore, + StoreOReillyStore, + StorePragmaticBookshelfStore, + StoreSmashwordsStore, + StoreWaterstonesUKStore, + StoreWeightlessBooksStore, + StoreWizardsTowerBooksStore +] # }}} diff --git a/src/calibre/gui2/bars.py b/src/calibre/gui2/bars.py index 7dc0567d95..58711f9096 100644 --- a/src/calibre/gui2/bars.py +++ b/src/calibre/gui2/bars.py @@ -249,6 +249,10 @@ class BarsManager(QObject): self.menu_bar = MenuBar(self.location_manager, self.parent()) self.parent().setMenuBar(self.menu_bar) + parent.addToolBar(Qt.TopToolBarArea, self.main_bars[0]) + parent.addToolBar(Qt.BottomToolBarArea, self.main_bars[1]) + parent.addToolBar(Qt.BottomToolBarArea, self.child_bars[0]) + self.apply_settings() self.init_bars() @@ -288,12 +292,15 @@ class BarsManager(QObject): ''' showing_device = self.location_manager.has_device main_bar = self.main_bars[1 if showing_device else 0] + hidden_bar = self.main_bars[0 if showing_device else 1] + self.parent().addToolBar(Qt.BottomToolBarArea, hidden_bar) child_bar = self.child_bars[0] for bar in self.bars: bar.setVisible(False) bar.update_lm_actions() if main_bar.added_actions: main_bar.setVisible(True) + self.parent().addToolBar(Qt.TopToolBarArea, main_bar) if child_bar.added_actions: child_bar.setVisible(True) diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index 46b6356a6e..85e79d66d3 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -259,10 +259,6 @@ class MainWindowMixin(object): # {{{ self.search_bar = SearchBar(self) self.bars_manager = BarsManager(self.donate_button, self.location_manager, self) - for bar in self.bars_manager.main_bars: - self.addToolBar(Qt.TopToolBarArea, bar) - for bar in self.bars_manager.child_bars: - self.addToolBar(Qt.BottomToolBarArea, bar) self.bars_manager.update_bars() self.setUnifiedTitleAndToolBarOnMac(True) diff --git a/src/calibre/gui2/store/gandalf_plugin.py b/src/calibre/gui2/store/gandalf_plugin.py new file mode 100644 index 0000000000..4bd8e9e747 --- /dev/null +++ b/src/calibre/gui2/store/gandalf_plugin.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- + +from __future__ import (unicode_literals, division, absolute_import, print_function) + +__license__ = 'GPL 3' +__copyright__ = '2011, Tomasz Długosz ' +__docformat__ = 'restructuredtext en' + +import re +import urllib +from contextlib import closing + +from lxml import html + +from PyQt4.Qt import QUrl + +from calibre import browser, url_slash_cleaner +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 GandalfStore(BasicStoreConfig, StorePlugin): + + def open(self, parent=None, detail_item=None, external=False): + url = 'http://www.gandalf.com.pl/ebooks/' + + if external or self.config.get('open_external', False): + open_url(QUrl(url_slash_cleaner(detail_item if detail_item else url))) + else: + d = WebStoreDialog(self.gui, url, parent, detail_item) + 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.gandalf.com.pl/s/' + values={ + 'search': query.encode('iso8859_2'), + 'dzialx':'11' + } + + br = browser() + + counter = max_results + with closing(br.open(url, data=urllib.urlencode(values), timeout=timeout)) as f: + doc = html.fromstring(f.read()) + for data in doc.xpath('//div[@class="box"]'): + if counter <= 0: + break + + id = ''.join(data.xpath('.//div[@class="info"]/h3/a/@href')) + if not id: + continue + + cover_url = ''.join(data.xpath('.//img/@src')) + title = ''.join(data.xpath('.//div[@class="info"]/h3/a/@title')) + formats = title.split() + formats = formats[-1] + author = ''.join(data.xpath('.//div[@class="info"]/h4/text() | .//div[@class="info"]/h4/span/text()')) + price = ''.join(data.xpath('.//h3[@class="promocja"]/text()')) + price = re.sub('PLN', 'zł', price) + price = re.sub('\.', ',', price) + + counter -= 1 + + s = SearchResult() + s.cover_url = cover_url + s.title = title.strip() + s.author = author.strip() + s.price = price + s.detail_item = id.strip() + s.drm = SearchResult.DRM_UNKNOWN + s.formats = formats.upper().strip() + + yield s diff --git a/src/calibre/gui2/store/nexto_plugin.py b/src/calibre/gui2/store/nexto_plugin.py index d63cf18233..0009f39b1b 100644 --- a/src/calibre/gui2/store/nexto_plugin.py +++ b/src/calibre/gui2/store/nexto_plugin.py @@ -63,6 +63,7 @@ class NextoStore(BasicStoreConfig, StorePlugin): cover_url = ''.join(data.xpath('.//img[@class="cover"]/@src')) title = ''.join(data.xpath('.//a[@class="title"]/text()')) + title = re.sub(r' - ebook$', '', title) formats = ', '.join(data.xpath('.//ul[@class="formats_available"]/li//b/text()')) DrmFree = re.search(r'bez.DRM', formats) formats = re.sub(r'\(.+\)', '', formats) diff --git a/src/calibre/gui2/store/pragmatic_bookshelf_plugin.py b/src/calibre/gui2/store/pragmatic_bookshelf_plugin.py new file mode 100644 index 0000000000..f3803bbcea --- /dev/null +++ b/src/calibre/gui2/store/pragmatic_bookshelf_plugin.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- + +from __future__ import (unicode_literals, division, absolute_import, print_function) + +__license__ = 'GPL 3' +__copyright__ = '2011, John Schember ' +__docformat__ = 'restructuredtext en' + +import urllib +from contextlib import closing + +from lxml import html + +from PyQt4.Qt import QUrl + +from calibre import browser, url_slash_cleaner +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 PragmaticBookshelfStore(BasicStoreConfig, StorePlugin): + + def open(self, parent=None, detail_item=None, external=False): + url = 'http://pragprog.com/' + + if external or self.config.get('open_external', False): + open_url(QUrl(url_slash_cleaner(detail_item if detail_item else url))) + else: + d = WebStoreDialog(self.gui, url, parent, detail_item) + d.setWindowTitle(self.name) + d.set_tags(self.config.get('tags', '')) + d.exec_() + + def search(self, query, max_results=10, timeout=60): + ''' + OPDS based search. + + We really should get the catelog from http://pragprog.com/catalog.opds + and look for the application/opensearchdescription+xml entry. + Then get the opensearch description to get the search url and + format. However, we are going to be lazy and hard code it. + ''' + url = 'http://pragprog.com/catalog/search?q=' + urllib.quote_plus(query) + + br = browser() + + counter = max_results + with closing(br.open(url, timeout=timeout)) as f: + # Use html instead of etree as html allows us + # to ignore the namespace easily. + doc = html.fromstring(f.read()) + for data in doc.xpath('//entry'): + if counter <= 0: + break + + id = ''.join(data.xpath('.//link[@rel="http://opds-spec.org/acquisition/buy"]/@href')) + if not id: + continue + + price = ''.join(data.xpath('.//price/@currencycode')).strip() + price += ' ' + price += ''.join(data.xpath('.//price/text()')).strip() + if not price.strip(): + continue + + cover_url = ''.join(data.xpath('.//link[@rel="http://opds-spec.org/cover"]/@href')) + + title = ''.join(data.xpath('.//title/text()')) + author = ''.join(data.xpath('.//author//text()')) + + counter -= 1 + + s = SearchResult() + s.cover_url = cover_url + s.title = title.strip() + s.author = author.strip() + s.price = price.strip() + s.detail_item = id.strip() + s.drm = SearchResult.DRM_UNLOCKED + s.formats = 'EPUB, PDF, MOBI' + + yield s diff --git a/src/calibre/gui2/store/search/search.py b/src/calibre/gui2/store/search/search.py index e0d0251f98..f9ac45e707 100644 --- a/src/calibre/gui2/store/search/search.py +++ b/src/calibre/gui2/store/search/search.py @@ -190,7 +190,7 @@ class SearchDialog(QDialog, Ui_Dialog): else: self.resize_columns() - self.open_external.setChecked(self.config.get('open_external', False)) + self.open_external.setChecked(self.config.get('open_external', True)) store_check = self.config.get('store_checked', None) if store_check: