Merge stores from lp:~cbhaley/calibre/charles_store

This commit is contained in:
John Schember 2011-05-10 18:34:32 -04:00
commit d9aa8a3916
10 changed files with 239 additions and 48 deletions

View File

@ -1116,6 +1116,11 @@ class StoreBNStore(StoreBase):
description = _('Books, Textbooks, eBooks, Toys, Games and More.') description = _('Books, Textbooks, eBooks, Toys, Games and More.')
actual_plugin = 'calibre.gui2.store.bn_plugin:BNStore' actual_plugin = 'calibre.gui2.store.bn_plugin:BNStore'
class StoreBeamEBooksDEStore(StoreBase):
name = 'Beam EBooks DE'
description = _('der eBook Shop')
actual_plugin = 'calibre.gui2.store.beam_ebooks_de_plugin:BeamEBooksDEStore'
class StoreBeWriteStore(StoreBase): class StoreBeWriteStore(StoreBase):
name = 'BeWrite Books' name = 'BeWrite Books'
description = _('Publishers of fine books.') description = _('Publishers of fine books.')
@ -1131,7 +1136,12 @@ class StoreEbookscomStore(StoreBase):
description = _('The digital bookstore.') description = _('The digital bookstore.')
actual_plugin = 'calibre.gui2.store.ebooks_com_plugin:EbookscomStore' actual_plugin = 'calibre.gui2.store.ebooks_com_plugin:EbookscomStore'
class StoreEHarlequinStoretore(StoreBase): class StoreEPubBuyDEStore(StoreBase):
name = 'EPUBBuy DE'
description = _('EPUBReaders eBook Shop')
actual_plugin = 'calibre.gui2.store.epubbuy_de_plugin:EPubBuyDEStore'
class StoreEHarlequinStore(StoreBase):
name = 'eHarlequin' name = 'eHarlequin'
description = _('entertain, enrich, inspire.') description = _('entertain, enrich, inspire.')
actual_plugin = 'calibre.gui2.store.eharlequin_plugin:EHarlequinStore' actual_plugin = 'calibre.gui2.store.eharlequin_plugin:EHarlequinStore'
@ -1193,9 +1203,9 @@ class StoreWizardsTowerBooksStore(StoreBase):
plugins += [StoreAmazonKindleStore, StoreAmazonDEKindleStore, StoreAmazonUKKindleStore, plugins += [StoreAmazonKindleStore, StoreAmazonDEKindleStore, StoreAmazonUKKindleStore,
StoreBaenWebScriptionStore, StoreBNStore, StoreBaenWebScriptionStore, StoreBNStore,
StoreBeWriteStore, StoreBeamEBooksDEStore, StoreBeWriteStore,
StoreDieselEbooksStore, StoreEbookscomStore, StoreDieselEbooksStore, StoreEbookscomStore, StoreEPubBuyDEStore,
StoreEHarlequinStoretore, StoreFeedbooksStore, StoreEHarlequinStore, StoreFeedbooksStore,
StoreFoylesUKStore, StoreGutenbergStore, StoreKoboStore, StoreManyBooksStore, StoreFoylesUKStore, StoreGutenbergStore, StoreKoboStore, StoreManyBooksStore,
StoreMobileReadStore, StoreOpenLibraryStore, StoreSmashwordsStore, StoreMobileReadStore, StoreOpenLibraryStore, StoreSmashwordsStore,
StoreWaterstonesUKStore, StoreWeightlessBooksStore, StoreWizardsTowerBooksStore] StoreWaterstonesUKStore, StoreWeightlessBooksStore, StoreWizardsTowerBooksStore]

View File

@ -203,9 +203,11 @@ class ITUNES(DriverBase):
# 0x1294 iPhone 3GS # 0x1294 iPhone 3GS
# 0x1297 iPhone 4 # 0x1297 iPhone 4
# 0x129a iPad # 0x129a iPad
# 0x12a2 iPad2 # 0x129f iPad2 (WiFi)
# 0x12a2 iPad2 (GSM)
# 0x12a3 iPad2 (CDMA)
VENDOR_ID = [0x05ac] 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] BCD = [0x01]
# Plugboard ID # Plugboard ID

View File

@ -7,7 +7,6 @@ __copyright__ = '2011, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import os import os
import posixpath
from calibre import guess_type, walk from calibre import guess_type, walk
from calibre.customize.conversion import InputFormatPlugin from calibre.customize.conversion import InputFormatPlugin
@ -74,22 +73,23 @@ class HTMLZInput(InputFormatPlugin):
meta_info_to_oeb_metadata(mi, oeb.metadata, log) meta_info_to_oeb_metadata(mi, oeb.metadata, log)
# Get the cover path from the OPF. # Get the cover path from the OPF.
cover_href = None cover_path = None
opf = None opf = None
for x in walk('.'): for x in walk('.'):
if os.path.splitext(x)[1].lower() in ('.opf'): if os.path.splitext(x)[1].lower() in ('.opf'):
opf = x opf = x
break break
if opf: if opf:
opf = OPF(opf) opf = OPF(opf, basedir=os.getcwd())
cover_href = posixpath.relpath(opf.cover, os.path.dirname(stream.name)) cover_path = opf.raster_cover
# Set the cover. # Set the cover.
if cover_href: if cover_path:
cdata = None cdata = None
with open(cover_href, 'rb') as cf: with open(os.path.join(os.getcwd(), cover_path), 'rb') as cf:
cdata = cf.read() cdata = cf.read()
id, href = oeb.manifest.generate('cover', cover_href) cover_name = os.path.basename(cover_path)
oeb.manifest.add(id, href, guess_type(cover_href)[0], data=cdata) 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) oeb.guide.add('cover', 'Cover', href)
return oeb return oeb

View File

@ -8,12 +8,11 @@ Read meta information from extZ (TXTZ, HTMLZ...) files.
''' '''
import os import os
import posixpath
from cStringIO import StringIO from cStringIO import StringIO
from calibre.ebooks.metadata import MetaInformation 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.ptempfile import PersistentTemporaryFile
from calibre.utils.zipfile import ZipFile, safe_replace from calibre.utils.zipfile import ZipFile, safe_replace
@ -31,9 +30,9 @@ def get_metadata(stream, extract_cover=True):
opf = OPF(opf_stream) opf = OPF(opf_stream)
mi = opf.to_book_metadata() mi = opf.to_book_metadata()
if extract_cover: if extract_cover:
cover_href = posixpath.relpath(opf.cover, os.path.dirname(stream.name)) cover_href = opf.raster_cover
if cover_href: 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: except:
return mi return mi
return mi return mi
@ -59,18 +58,15 @@ def set_metadata(stream, mi):
except: except:
pass pass
if new_cdata: if new_cdata:
cover = opf.cover cpath = opf.raster_cover
if not cover: if not cpath:
cover = 'cover.jpg' cpath = 'cover.jpg'
cpath = posixpath.join(posixpath.dirname(opf_path), cover)
new_cover = _write_new_cover(new_cdata, cpath) new_cover = _write_new_cover(new_cdata, cpath)
replacements[cpath] = open(new_cover.name, 'rb') replacements[cpath] = open(new_cover.name, 'rb')
mi.cover = cover mi.cover = cpath
# Update the metadata. # Update the metadata.
old_mi = opf.to_book_metadata() opf.smart_update(mi, replace_metadata=True)
old_mi.smart_update(mi)
opf.smart_update(metadata_to_opf(old_mi), replace_metadata=True)
newopf = StringIO(opf.render()) newopf = StringIO(opf.render())
safe_replace(stream, opf_path, newopf, extra_replacements=replacements, add_missing=True) safe_replace(stream, opf_path, newopf, extra_replacements=replacements, add_missing=True)

View File

@ -19,9 +19,13 @@ class MessageBox(QDialog, Ui_Dialog): # {{{
INFO = 2 INFO = 2
QUESTION = 3 QUESTION = 3
def __init__(self, type_, title, msg, det_msg='', show_copy_button=True, def __init__(self, type_, title, msg,
det_msg='',
q_icon=None,
show_copy_button=True,
parent=None): parent=None):
QDialog.__init__(self, parent) QDialog.__init__(self, parent)
if q_icon is None:
icon = { icon = {
self.ERROR : 'error', self.ERROR : 'error',
self.WARNING: 'warning', self.WARNING: 'warning',
@ -30,6 +34,8 @@ class MessageBox(QDialog, Ui_Dialog): # {{{
}[type_] }[type_]
icon = 'dialog_%s.png'%icon icon = 'dialog_%s.png'%icon
self.icon = QIcon(I(icon)) self.icon = QIcon(I(icon))
else:
self.icon = q_icon
self.setupUi(self) self.setupUi(self)
self.setWindowTitle(title) self.setWindowTitle(title)
@ -44,7 +50,6 @@ class MessageBox(QDialog, Ui_Dialog): # {{{
self.bb.ActionRole) self.bb.ActionRole)
self.ctc_button.clicked.connect(self.copy_to_clipboard) self.ctc_button.clicked.connect(self.copy_to_clipboard)
self.show_det_msg = _('Show &details') self.show_det_msg = _('Show &details')
self.hide_det_msg = _('Hide &details') self.hide_det_msg = _('Hide &details')
self.det_msg_toggle = self.bb.addButton(self.show_det_msg, self.bb.ActionRole) self.det_msg_toggle = self.bb.addButton(self.show_det_msg, self.bb.ActionRole)

View File

@ -31,6 +31,7 @@ class MetadataSingleDialogBase(ResizableDialog):
view_format = pyqtSignal(object, object) view_format = pyqtSignal(object, object)
cc_two_column = tweaks['metadata_single_use_2_cols_for_custom_fields'] cc_two_column = tweaks['metadata_single_use_2_cols_for_custom_fields']
one_line_comments_toolbar = False one_line_comments_toolbar = False
use_toolbutton_for_config_metadata = True
def __init__(self, db, parent=None): def __init__(self, db, parent=None):
self.db = db self.db = db
@ -71,7 +72,9 @@ class MetadataSingleDialogBase(ResizableDialog):
self.l.addWidget(self.scroll_area) self.l.addWidget(self.scroll_area)
ll = self.button_box_layout = QHBoxLayout() ll = self.button_box_layout = QHBoxLayout()
self.l.addLayout(ll) self.l.addLayout(ll)
ll.addSpacing(10)
ll.addWidget(self.button_box) ll.addWidget(self.button_box)
ll.addSpacing(10)
self.setWindowIcon(QIcon(I('edit_input.png'))) self.setWindowIcon(QIcon(I('edit_input.png')))
self.setWindowTitle(_('Edit Metadata')) self.setWindowTitle(_('Edit Metadata'))
@ -191,8 +194,13 @@ class MetadataSingleDialogBase(ResizableDialog):
font.setBold(True) font.setBold(True)
self.fetch_metadata_button.setFont(font) self.fetch_metadata_button.setFont(font)
if self.use_toolbutton_for_config_metadata:
self.config_metadata_button = QToolButton(self) self.config_metadata_button = QToolButton(self)
self.config_metadata_button.setIcon(QIcon(I('config.png'))) self.config_metadata_button.setIcon(QIcon(I('config.png')))
else:
self.config_metadata_button = QPushButton(self)
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.clicked.connect(self.configure_metadata)
self.config_metadata_button.setToolTip( self.config_metadata_button.setToolTip(
_('Change how calibre downloads metadata')) _('Change how calibre downloads metadata'))
@ -614,6 +622,7 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
cc_two_column = False cc_two_column = False
one_line_comments_toolbar = True one_line_comments_toolbar = True
use_toolbutton_for_config_metadata = False
on_drag_enter = pyqtSignal() on_drag_enter = pyqtSignal()
@ -649,10 +658,8 @@ class MetadataSingleDialogAlt1(MetadataSingleDialogBase): # {{{
self.tabs[0].l.addWidget(gb, 0, 0, 1, 1) self.tabs[0].l.addWidget(gb, 0, 0, 1, 1)
gb.setLayout(tl) gb.setLayout(tl)
self.button_box_layout.insertWidget(0, self.fetch_metadata_button) self.button_box_layout.insertWidget(1, self.fetch_metadata_button)
self.config_metadata_button.setToolButtonStyle(Qt.ToolButtonTextOnly) self.button_box_layout.insertWidget(2, self.config_metadata_button)
self.config_metadata_button.setText(_('Configure metadata downloading'))
self.button_box_layout.insertWidget(1, self.config_metadata_button)
sto(self.button_box, self.fetch_metadata_button) sto(self.button_box, self.fetch_metadata_button)
sto(self.fetch_metadata_button, self.config_metadata_button) sto(self.fetch_metadata_button, self.config_metadata_button)
sto(self.config_metadata_button, self.title) sto(self.config_metadata_button, self.title)
@ -767,6 +774,7 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
cc_two_column = False cc_two_column = False
one_line_comments_toolbar = True one_line_comments_toolbar = True
use_toolbutton_for_config_metadata = False
def do_layout(self): def do_layout(self):
self.central_widget.clear() self.central_widget.clear()
@ -785,10 +793,8 @@ class MetadataSingleDialogAlt2(MetadataSingleDialogBase): # {{{
l.addWidget(gb, 0, 0, 1, 1) l.addWidget(gb, 0, 0, 1, 1)
gb.setLayout(tl) gb.setLayout(tl)
self.button_box_layout.insertWidget(0, self.fetch_metadata_button) self.button_box_layout.insertWidget(1, self.fetch_metadata_button)
self.config_metadata_button.setToolButtonStyle(Qt.ToolButtonTextOnly) self.button_box_layout.insertWidget(2, self.config_metadata_button)
self.config_metadata_button.setText(_('Configure metadata downloading'))
self.button_box_layout.insertWidget(1, self.config_metadata_button)
sto(self.button_box, self.fetch_metadata_button) sto(self.button_box, self.fetch_metadata_button)
sto(self.fetch_metadata_button, self.config_metadata_button) sto(self.fetch_metadata_button, self.config_metadata_button)
sto(self.config_metadata_button, self.title) sto(self.config_metadata_button, self.title)

View File

@ -0,0 +1,92 @@
# -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function)
__license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
__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://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:
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)
br = browser()
counter = max_results
with closing(br.open(url, timeout=timeout)) as f:
doc = html.fromstring(f.read())
for data in doc.xpath('//table[tr/td/div[@class="stil2"]]'):
if counter <= 0:
break
id = ''.join(data.xpath('./tr/td/div[@class="stil2"]/a/@href')).strip()
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()'))
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()
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

View File

@ -0,0 +1,80 @@
# -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import, print_function)
__license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
__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://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:
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"]'
'/p[contains(text(), "artnr:")]/text()')).strip()
if not id:
continue
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'))
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

View File

@ -73,6 +73,6 @@ class FoylesUKStore(BasicStoreConfig, StorePlugin):
s.price = price s.price = price
s.detail_item = id s.detail_item = id
s.drm = SearchResult.DRM_LOCKED s.drm = SearchResult.DRM_LOCKED
s.formats = 'EPUB' s.formats = 'ePub'
yield s yield s

View File

@ -76,7 +76,7 @@ class WaterstonesUKStore(BasicStoreConfig, StorePlugin):
s.detail_item = id s.detail_item = id
formats = [] formats = []
if epub: if epub:
formats.append('EPUB') formats.append('ePub')
if pdf: if pdf:
formats.append('PDF') formats.append('PDF')
s.formats = ', '.join(formats) s.formats = ', '.join(formats)