web_control downloads ebook links. Add Project Gutenberg store plugin.

This commit is contained in:
John Schember 2011-02-25 08:47:09 -05:00
parent 6d568aee69
commit c890651806
10 changed files with 133 additions and 43 deletions

View File

@ -1041,8 +1041,9 @@ plugins += [GoogleBooks]
# }}} # }}}
# Store plugins {{{ # Store plugins {{{
from calibre.gui2.store.amazon.amazon_plugin import AmazonKindleStore from calibre.gui2.store.amazon_plugin import AmazonKindleStore
from calibre.gui2.store.gutenberg_plugin import GutenbergStore
plugins += [AmazonKindleStore] plugins += [AmazonKindleStore, GutenbergStore]
# }}} # }}}

View File

@ -1,19 +0,0 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
from PyQt4.Qt import QWebView, QWebPage
class NPWebView(QWebView):
def createWindow(self, type):
if type == QWebPage.WebBrowserWindow:
return self
else:
return None

View File

@ -18,9 +18,12 @@ class AmazonKindleStore(StorePlugin):
name = 'Amazon Kindle' name = 'Amazon Kindle'
description = _('Buy Kindle books from Amazon') description = _('Buy Kindle books from Amazon')
ASTORE_URL = 'http://astore.amazon.com/josbl0e-20/'
def open(self, gui, parent=None, start_item=None): def open(self, gui, parent=None, start_item=None):
from calibre.gui2.store.amazon.amazon_kindle_dialog import AmazonKindleDialog from calibre.gui2.store.web_store_dialog import WebStoreDialog
d = AmazonKindleDialog(gui, parent, start_item) d = WebStoreDialog(gui, self.ASTORE_URL, parent, start_item)
d.setWindowTitle('Amazon Kindle Store')
d = d.exec_() d = d.exec_()
def search(self, query, max_results=10, timeout=60): def search(self, query, max_results=10, timeout=60):
@ -58,4 +61,4 @@ class AmazonKindleStore(StorePlugin):
continue continue
counter -= 1 counter -= 1
yield ('', title.strip(), author.strip(), price.strip(), asin.strip()) yield ('', title.strip(), author.strip(), price.strip(), '/detail/'+asin.strip())

View File

@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
import urllib2
from contextlib import closing
from lxml import html
from calibre import browser
from calibre.customize import StorePlugin
class GutenbergStore(StorePlugin):
name = 'Project Gutenberg'
description = _('The first producer of free ebooks.')
def open(self, gui, parent=None, start_item=None):
from calibre.gui2.store.web_store_dialog import WebStoreDialog
d = WebStoreDialog(gui, 'http://m.gutenberg.org/', parent, start_item)
d.setWindowTitle('Free eBooks by Project Gutenberg')
d = d.exec_()
def search(self, query, max_results=10, timeout=60):
url = 'http://www.google.com/xhtml?q=site:gutenberg.org+' + 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('//div[@class="edewpi"]//div[@class="r ld"]'):
if counter <= 0:
break
heading = ''.join(data.xpath('div[@class="jd"]/a//text()'))
title, _, author = heading.partition('by')
author = author.split('-')[0]
price = '$0.00'
url = ''.join(data.xpath('span[@class="c"]/text()'))
id = url.split('/')[-1]
counter -= 1
yield ('', title.strip(), author.strip(), price.strip(), '/ebooks/' + id.strip())

View File

@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL 3'
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
from PyQt4.Qt import QWebView, QWebPage, QNetworkCookieJar, QNetworkRequest
class NPWebView(QWebView):
def __init__(self, *args):
QWebView.__init__(self, *args)
self.gui = None
#self.setPage(NPWebPage())
self.page().networkAccessManager().setCookieJar(QNetworkCookieJar())
self.page().setForwardUnsupportedContent(True)
self.page().unsupportedContent.connect(self.start_download)
self.page().downloadRequested.connect(self.start_download)
self.page().networkAccessManager().sslErrors.connect(self.ignore_ssl_errors)
#self.page().networkAccessManager().finished.connect(self.fin)
def createWindow(self, type):
if type == QWebPage.WebBrowserWindow:
return self
else:
return None
def set_gui(self, gui):
self.gui = gui
def start_download(self, request):
if not self.gui:
print 'no gui'
return
url = unicode(request.url().toString())
self.gui.download_from_store(url)
def ignore_ssl_errors(self, reply, errors):
reply.ignoreSslErrors(errors)
def fin(self, reply):
if reply.error():
print 'error'
print reply.error()
#print reply.attribute(QNetworkRequest.HttpStatusCodeAttribute).toInt()
class NPWebPage(QWebPage):
def userAgentForUrl(self, url):
return 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.102 Safari/534.13'

View File

@ -8,39 +8,41 @@ import urllib
from PyQt4.Qt import QDialog, QUrl from PyQt4.Qt import QDialog, QUrl
from calibre.gui2.store.amazon.amazon_kindle_dialog_ui import Ui_Dialog from calibre.gui2.store.web_store_dialog_ui import Ui_Dialog
class AmazonKindleDialog(QDialog, Ui_Dialog): class WebStoreDialog(QDialog, Ui_Dialog):
ASTORE_URL = 'http://astore.amazon.com/josbl0e-20/' def __init__(self, gui, base_url, parent=None, detail_item=None):
def __init__(self, gui, parent=None, start_item=None):
QDialog.__init__(self, parent=parent) QDialog.__init__(self, parent=parent)
self.setupUi(self) self.setupUi(self)
self.gui = gui self.gui = gui
self.base_url = base_url
self.view.set_gui(self.gui)
self.view.loadStarted.connect(self.load_started) self.view.loadStarted.connect(self.load_started)
self.view.loadProgress.connect(self.load_progress) self.view.loadProgress.connect(self.load_progress)
self.view.loadFinished.connect(self.load_finished) self.view.loadFinished.connect(self.load_finished)
self.home.clicked.connect(self.go_home) self.home.clicked.connect(self.go_home)
self.reload.clicked.connect(self.go_reload) self.reload.clicked.connect(self.go_reload)
self.go_home(start_item=start_item) self.go_home(detail_item=detail_item)
def load_started(self): def load_started(self):
self.progress.setValue(0) self.progress.setValue(0)
def load_progress(self, val): def load_progress(self, val):
self.progress.setValue(val) self.progress.setValue(val)
def load_finished(self): def load_finished(self, ok=True):
self.progress.setValue(100) self.progress.setValue(100)
#if not ok:
# print 'Error'
def go_home(self, checked=False, start_item=None): def go_home(self, checked=False, detail_item=None):
url = self.ASTORE_URL url = self.base_url
if start_item: if detail_item:
url += 'detail/' + urllib.quote(start_item) url += '/' + urllib.quote(detail_item)
self.view.load(QUrl(url)) self.view.load(QUrl(url))
def go_reload(self, checked=False): def go_reload(self, checked=False):

View File

@ -11,7 +11,7 @@
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Amazon Kindle Store</string> <string/>
</property> </property>
<property name="sizeGripEnabled"> <property name="sizeGripEnabled">
<bool>true</bool> <bool>true</bool>

View File

@ -93,7 +93,6 @@ class StoreDownloader(Thread):
self._download(job) self._download(job)
self._add(job) self._add(job)
self._save_as(job) self._save_as(job)
break
except Exception, e: except Exception, e:
if not self._run: if not self._run:
return return
@ -125,13 +124,13 @@ class StoreDownloader(Thread):
br = browser() br = browser()
basename = br.geturl(url).split('/')[-1] basename = br.open(url).geturl().split('/')[-1]
ext = os.path.splitext(basename)[1][1:].lower() ext = os.path.splitext(basename)[1][1:].lower()
if ext not in BOOK_EXTENSIONS: if ext not in BOOK_EXTENSIONS:
raise Exception(_('Not a valid ebook format.')) raise Exception(_('Not a valid ebook format.'))
tf = PersistentTemporaryFile(suffix=basename) tf = PersistentTemporaryFile(suffix=basename)
with closing(br.urlopen(url)) as f: with closing(br.open(url)) as f:
tf.write(f.read()) tf.write(f.read())
tf.close() tf.close()
job.tmp_file_name = tf.name job.tmp_file_name = tf.name
@ -141,7 +140,7 @@ class StoreDownloader(Thread):
if not add_to_lib and job.tmp_file_name: if not add_to_lib and job.tmp_file_name:
return return
ext = os.path.splitext(job.tmp_file_name)[1:] ext = os.path.splitext(job.tmp_file_name)[1][1:]
from calibre.ebooks.metadata.meta import get_metadata from calibre.ebooks.metadata.meta import get_metadata
with open(job.tmp_file_name) as f: with open(job.tmp_file_name) as f:
@ -151,14 +150,14 @@ class StoreDownloader(Thread):
def _save_as(self, job): def _save_as(self, job):
url, save_loc, add_to_lib = job.args url, save_loc, add_to_lib = job.args
if not save_loc and job.tmp_fie_name: if not save_loc and job.tmp_file_name:
return return
shutil.copy(job.tmp_fie_name, save_loc) shutil.copy(job.tmp_fie_name, save_loc)
def download_from_store(self, callback, db, url='', save_as_loc='', add_to_lib=True): def download_from_store(self, callback, db, url='', save_as_loc='', add_to_lib=True):
description = _('Downloading %s') % url description = _('Downloading %s') % url
job = StoreDownloadJob(callback, description, job_manager, db, url, save_as_loc, add_to_lib) job = StoreDownloadJob(callback, description, self.job_manager, db, url, save_as_loc, add_to_lib)
self.job_manager.add_job(job) self.job_manager.add_job(job)
self.jobs.put(job) self.jobs.put(job)

View File

@ -166,6 +166,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
LayoutMixin.__init__(self) LayoutMixin.__init__(self)
EmailMixin.__init__(self) EmailMixin.__init__(self)
StoreDownloadMixin.__init__(self)
DeviceMixin.__init__(self) DeviceMixin.__init__(self)
self.progress_indicator = ProgressIndicator(self) self.progress_indicator = ProgressIndicator(self)