mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
web_control downloads ebook links. Add Project Gutenberg store plugin.
This commit is contained in:
parent
6d568aee69
commit
c890651806
@ -1041,8 +1041,9 @@ plugins += [GoogleBooks]
|
||||
# }}}
|
||||
|
||||
# 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]
|
||||
|
||||
# }}}
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
@ -18,9 +18,12 @@ class AmazonKindleStore(StorePlugin):
|
||||
name = 'Amazon Kindle'
|
||||
description = _('Buy Kindle books from Amazon')
|
||||
|
||||
ASTORE_URL = 'http://astore.amazon.com/josbl0e-20/'
|
||||
|
||||
def open(self, gui, parent=None, start_item=None):
|
||||
from calibre.gui2.store.amazon.amazon_kindle_dialog import AmazonKindleDialog
|
||||
d = AmazonKindleDialog(gui, parent, start_item)
|
||||
from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
||||
d = WebStoreDialog(gui, self.ASTORE_URL, parent, start_item)
|
||||
d.setWindowTitle('Amazon Kindle Store')
|
||||
d = d.exec_()
|
||||
|
||||
def search(self, query, max_results=10, timeout=60):
|
||||
@ -58,4 +61,4 @@ class AmazonKindleStore(StorePlugin):
|
||||
continue
|
||||
|
||||
counter -= 1
|
||||
yield ('', title.strip(), author.strip(), price.strip(), asin.strip())
|
||||
yield ('', title.strip(), author.strip(), price.strip(), '/detail/'+asin.strip())
|
50
src/calibre/gui2/store/gutenberg_plugin.py
Normal file
50
src/calibre/gui2/store/gutenberg_plugin.py
Normal 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())
|
||||
|
||||
|
53
src/calibre/gui2/store/web_control.py
Normal file
53
src/calibre/gui2/store/web_control.py
Normal 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'
|
@ -8,25 +8,25 @@ import urllib
|
||||
|
||||
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, parent=None, start_item=None):
|
||||
def __init__(self, gui, base_url, parent=None, detail_item=None):
|
||||
QDialog.__init__(self, parent=parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.gui = gui
|
||||
self.base_url = base_url
|
||||
|
||||
self.view.set_gui(self.gui)
|
||||
self.view.loadStarted.connect(self.load_started)
|
||||
self.view.loadProgress.connect(self.load_progress)
|
||||
self.view.loadFinished.connect(self.load_finished)
|
||||
self.home.clicked.connect(self.go_home)
|
||||
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):
|
||||
self.progress.setValue(0)
|
||||
@ -34,13 +34,15 @@ class AmazonKindleDialog(QDialog, Ui_Dialog):
|
||||
def load_progress(self, val):
|
||||
self.progress.setValue(val)
|
||||
|
||||
def load_finished(self):
|
||||
def load_finished(self, ok=True):
|
||||
self.progress.setValue(100)
|
||||
#if not ok:
|
||||
# print 'Error'
|
||||
|
||||
def go_home(self, checked=False, start_item=None):
|
||||
url = self.ASTORE_URL
|
||||
if start_item:
|
||||
url += 'detail/' + urllib.quote(start_item)
|
||||
def go_home(self, checked=False, detail_item=None):
|
||||
url = self.base_url
|
||||
if detail_item:
|
||||
url += '/' + urllib.quote(detail_item)
|
||||
self.view.load(QUrl(url))
|
||||
|
||||
def go_reload(self, checked=False):
|
@ -11,7 +11,7 @@
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Amazon Kindle Store</string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>true</bool>
|
@ -93,7 +93,6 @@ class StoreDownloader(Thread):
|
||||
self._download(job)
|
||||
self._add(job)
|
||||
self._save_as(job)
|
||||
break
|
||||
except Exception, e:
|
||||
if not self._run:
|
||||
return
|
||||
@ -125,13 +124,13 @@ class StoreDownloader(Thread):
|
||||
|
||||
br = browser()
|
||||
|
||||
basename = br.geturl(url).split('/')[-1]
|
||||
basename = br.open(url).geturl().split('/')[-1]
|
||||
ext = os.path.splitext(basename)[1][1:].lower()
|
||||
if ext not in BOOK_EXTENSIONS:
|
||||
raise Exception(_('Not a valid ebook format.'))
|
||||
|
||||
tf = PersistentTemporaryFile(suffix=basename)
|
||||
with closing(br.urlopen(url)) as f:
|
||||
with closing(br.open(url)) as f:
|
||||
tf.write(f.read())
|
||||
tf.close()
|
||||
job.tmp_file_name = tf.name
|
||||
@ -141,7 +140,7 @@ class StoreDownloader(Thread):
|
||||
if not add_to_lib and job.tmp_file_name:
|
||||
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
|
||||
with open(job.tmp_file_name) as f:
|
||||
@ -151,14 +150,14 @@ class StoreDownloader(Thread):
|
||||
|
||||
def _save_as(self, job):
|
||||
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
|
||||
|
||||
shutil.copy(job.tmp_fie_name, save_loc)
|
||||
|
||||
def download_from_store(self, callback, db, url='', save_as_loc='', add_to_lib=True):
|
||||
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.jobs.put(job)
|
||||
|
||||
|
@ -166,6 +166,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
||||
|
||||
LayoutMixin.__init__(self)
|
||||
EmailMixin.__init__(self)
|
||||
StoreDownloadMixin.__init__(self)
|
||||
DeviceMixin.__init__(self)
|
||||
|
||||
self.progress_indicator = ProgressIndicator(self)
|
||||
|
Loading…
x
Reference in New Issue
Block a user