Start work on new metadata download GUIs

This commit is contained in:
Kovid Goyal 2011-04-06 21:51:03 -06:00
parent 58899e65ef
commit 5356225197
7 changed files with 167 additions and 7 deletions

View File

@ -279,7 +279,7 @@ class Worker(Thread): # Get details {{{
class Amazon(Source):
name = 'Amazon Metadata'
name = 'Amazon Store'
description = _('Downloads metadata from Amazon')
capabilities = frozenset(['identify', 'cover'])

View File

@ -167,6 +167,13 @@ class Source(Plugin):
# Configuration {{{
def is_configured(self):
'''
Return False if your plugin needs to be configured before it can be
used. For example, it might need a username/password/API key.
'''
return True
@property
def prefs(self):
if self._config_obj is None:

View File

@ -76,7 +76,7 @@ def run_download(log, results, abort,
(plugin, width, height, fmt, bytes)
'''
plugins = list(metadata_plugins(['cover']))
plugins = [p for p in metadata_plugins(['cover']) if p.is_configured()]
rq = Queue()
workers = [Worker(p, abort, title, authors, identifiers, timeout, rq) for p

View File

@ -250,7 +250,7 @@ def merge_identify_results(result_map, log):
def identify(log, abort, # {{{
title=None, authors=None, identifiers={}, timeout=30):
start_time = time.time()
plugins = list(metadata_plugins(['identify']))
plugins = [p for p in metadata_plugins(['identify']) if p.is_configured()]
kwargs = {
'title': title,

View File

@ -37,4 +37,7 @@ class ISBNDB(Source):
self.isbndb_key = prefs['isbndb_key']
def is_configured(self):
return self.isbndb_key is not None

View File

@ -7,8 +7,13 @@ __license__ = 'GPL v3'
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from PyQt4.Qt import (QStyledItemDelegate, QTextDocument, QRectF,
QStyle, QApplication)
from PyQt4.Qt import (QStyledItemDelegate, QTextDocument, QRectF, QIcon, Qt,
QStyle, QApplication, QDialog, QVBoxLayout, QLabel, QDialogButtonBox,
QStackedWidget, QWidget, QTableView, QGridLayout, QFontInfo, QPalette)
from PyQt4.QtWebKit import QWebView
from calibre.customize.ui import metadata_plugins
from calibre.ebooks.metadata import authors_to_string
class RichTextDelegate(QStyledItemDelegate): # {{{
@ -37,3 +42,148 @@ class RichTextDelegate(QStyledItemDelegate): # {{{
painter.restore()
# }}}
class ResultsView(QTableView):
def __init__(self, parent=None):
QTableView.__init__(self, parent)
class Comments(QWebView): # {{{
def __init__(self, parent=None):
QWebView.__init__(self, parent)
self.setAcceptDrops(False)
self.setMaximumWidth(270)
self.setMinimumWidth(270)
palette = self.palette()
palette.setBrush(QPalette.Base, Qt.transparent)
self.page().setPalette(palette)
self.setAttribute(Qt.WA_OpaquePaintEvent, False)
def turnoff_scrollbar(self, *args):
self.page().mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
def show_data(self, html):
def color_to_string(col):
ans = '#000000'
if col.isValid():
col = col.toRgb()
if col.isValid():
ans = unicode(col.name())
return ans
f = QFontInfo(QApplication.font(self.parent())).pixelSize()
c = color_to_string(QApplication.palette().color(QPalette.Normal,
QPalette.WindowText))
templ = '''\
<html>
<head>
<style type="text/css">
body, td {background-color: transparent; font-size: %dpx; color: %s }
a { text-decoration: none; color: blue }
div.description { margin-top: 0; padding-top: 0; text-indent: 0 }
table { margin-bottom: 0; padding-bottom: 0; }
</style>
</head>
<body>
<div class="description">
%%s
</div>
</body>
<html>
'''%(f, c)
self.setHtml(templ%html)
# }}}
class IdentifyWidget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.l = l = QGridLayout()
self.setLayout(l)
names = ['<b>'+p.name+'</b>' for p in metadata_plugins(['identify']) if
p.is_configured()]
self.top = QLabel('<p>'+_('calibre is downloading metadata from: ') +
', '.join(names))
self.top.setWordWrap(True)
l.addWidget(self.top, 0, 0)
self.results_view = ResultsView(self)
l.addWidget(self.results_view, 1, 0)
self.comments_view = Comments(self)
l.addWidget(self.comments_view, 1, 1)
self.query = QLabel('download starting...')
f = self.query.font()
f.setPointSize(f.pointSize()-2)
self.query.setFont(f)
self.query.setWordWrap(True)
l.addWidget(self.query, 2, 0, 1, 2)
def start(self, title=None, authors=None, identifiers={}):
parts = []
if title:
parts.append('title:'+title)
if authors:
parts.append('authors:'+authors_to_string(authors))
if identifiers:
x = ', '.join('%s:%s'%(k, v) for k, v in identifiers)
parts.append(x)
self.query.setText(_('Query: ')+'; '.join(parts))
self.comments_view.show_data('<h2>'+_('Downloading, please wait')+
'<span id="dots">.</span></h2>'+
'''
<script type="text/javascript">
window.onload=function(){
var dotspan = document.getElementById('dots');
window.setInterval(function(){
if(dotspan.textContent == '...'){
dotspan.textContent = '.';
}
else{
dotspan.textContent += '.';
}
}, 500);
}
</script>
''')
class FullFetch(QDialog): # {{{
def __init__(self, parent=None):
QDialog.__init__(self, parent)
self.setWindowTitle(_('Downloading metadata...'))
self.setWindowIcon(QIcon(I('metadata.png')))
self.stack = QStackedWidget()
self.l = l = QVBoxLayout()
self.setLayout(l)
l.addWidget(self.stack)
self.bb = QDialogButtonBox(QDialogButtonBox.Cancel)
l.addWidget(self.bb)
self.bb.rejected.connect(self.reject)
self.identify_widget = IdentifyWidget(self)
self.stack.addWidget(self.identify_widget)
self.resize(850, 500)
def accept(self):
# Prevent pressing Enter from closing the dialog
pass
def start(self, title=None, authors=None, identifiers={}):
self.identify_widget.start(title=title, authors=authors,
identifiers=identifiers)
self.exec_()
# }}}
if __name__ == '__main__':
app = QApplication([])
d = FullFetch()
d.start(title='great gatsby', authors=['Fitzgerald'])

View File

@ -16,7 +16,7 @@ Here, we will show you how to integrate the |app| content server into another se
Using a reverse proxy
-----------------------
This is the simplest approach as it allows you to use the binary calibre install with no external dependencies/system integration requirements.
A reverse proxy is when your normal server accepts incoming requests and passes them onto the calibre server. It then reads the response from the calibre server and forwards it to the client. This means that you can simply run the calibre server as normal without trying to integrate it closely with your main server, and you can take advantage of whatever authentication systems you main server has in place. This is the simplest approach as it allows you to use the binary calibre install with no external dependencies/system integration requirements. Below, is an example of how to achieve this with Apache as your main server, but it will work with any server that supports Reverse Proxies.
First start the |app| content server as shown below::
@ -33,7 +33,7 @@ The exact technique for enabling the proxy modules will vary depending on your A
RewriteRule ^/calibre/(.*) http://localhost:8080/calibre/$1 [proxy]
RewriteRule ^/calibre http://localhost:8080 [proxy]
That's all, you will now be able to access the |app| Content Server under the /calibre URL in your apache server.
That's all, you will now be able to access the |app| Content Server under the /calibre URL in your apache server. The above rules pass all requests under /calibre to the calibre server running on port 8080 and thanks to the --url-prefix option above, the calibre server handles them transparently.
.. note:: If you are willing to devote an entire VirtualHost to the content server, then there is no need to use --url-prefix and RewriteRule, instead just use the ProxyPass directive.