diff --git a/src/calibre/gui2/metadata/single_download.py b/src/calibre/gui2/metadata/single_download.py index be521b6000..426d0b9e78 100644 --- a/src/calibre/gui2/metadata/single_download.py +++ b/src/calibre/gui2/metadata/single_download.py @@ -7,6 +7,8 @@ __license__ = 'GPL v3' __copyright__ = '2011, Kovid Goyal ' __docformat__ = 'restructuredtext en' +from threading import Thread, Event + from PyQt4.Qt import (QStyledItemDelegate, QTextDocument, QRectF, QIcon, Qt, QStyle, QApplication, QDialog, QVBoxLayout, QLabel, QDialogButtonBox, QStackedWidget, QWidget, QTableView, QGridLayout, QFontInfo, QPalette) @@ -14,6 +16,18 @@ from PyQt4.QtWebKit import QWebView from calibre.customize.ui import metadata_plugins from calibre.ebooks.metadata import authors_to_string +from calibre.utils.logging import ThreadSafeLog, UnicodeHTMLStream +from calibre.ebooks.metadata.sources.identify import identify + +class Log(ThreadSafeLog): # {{{ + + def __init__(self): + ThreadSafeLog.__init__(self, level=self.DEBUG) + self.outputs = [UnicodeHTMLStream()] + + def clear(self): + self.outputs[0].clear() +# }}} class RichTextDelegate(QStyledItemDelegate): # {{{ @@ -95,10 +109,35 @@ class Comments(QWebView): # {{{ self.setHtml(templ%html) # }}} +class IdentifyWorker(Thread): + + def __init__(self, log, abort, title, authors, identifiers): + Thread.__init__(self) + self.daemon = True + + self.log, self.abort = log, abort + self.title, self.authors, self.identifiers = (title, authors. + identifiers) + + self.results = [] + self.error = None + + def run(self): + try: + self.results = identify(self.log, self.abort, title=self.title, + authors=self.authors, identifiers=self.identifiers) + for i, result in enumerate(self.results): + result.gui_rank = i + except: + import traceback + self.error = traceback.format_exc() + class IdentifyWidget(QWidget): - def __init__(self, parent=None): + def __init__(self, log, parent=None): QWidget.__init__(self, parent) + self.log = log + self.abort = Event() self.l = l = QGridLayout() self.setLayout(l) @@ -123,7 +162,27 @@ class IdentifyWidget(QWidget): self.query.setWordWrap(True) l.addWidget(self.query, 2, 0, 1, 2) + self.comments_view.show_data('

'+_('Downloading')+ + '
.

'+ + ''' + + ''') + def start(self, title=None, authors=None, identifiers={}): + self.log.clear() + self.log('Starting download') parts = [] if title: parts.append('title:'+title) @@ -133,28 +192,18 @@ class IdentifyWidget(QWidget): 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('

'+_('Downloading, please wait')+ - '.

'+ - ''' - - ''') + self.log(unicode(self.query.text())) + + self.worker = IdentifyWorker(self.log, self.abort, self.title, + self.authors, self.identifiers) + + # self.worker.start() class FullFetch(QDialog): # {{{ - def __init__(self, parent=None): + def __init__(self, log, parent=None): QDialog.__init__(self, parent) + self.log = log self.setWindowTitle(_('Downloading metadata...')) self.setWindowIcon(QIcon(I('metadata.png'))) @@ -168,7 +217,7 @@ class FullFetch(QDialog): # {{{ l.addWidget(self.bb) self.bb.rejected.connect(self.reject) - self.identify_widget = IdentifyWidget(self) + self.identify_widget = IdentifyWidget(log, self) self.stack.addWidget(self.identify_widget) self.resize(850, 500) @@ -184,6 +233,6 @@ class FullFetch(QDialog): # {{{ if __name__ == '__main__': app = QApplication([]) - d = FullFetch() + d = FullFetch(Log()) d.start(title='great gatsby', authors=['Fitzgerald']) diff --git a/src/calibre/utils/logging.py b/src/calibre/utils/logging.py index f4b2e6f0b6..45e21ded39 100644 --- a/src/calibre/utils/logging.py +++ b/src/calibre/utils/logging.py @@ -14,7 +14,7 @@ import sys, traceback, cStringIO from functools import partial from threading import RLock - +from calibre import isbytestring, force_unicode, as_unicode class Stream(object): @@ -63,15 +63,16 @@ class FileStream(Stream): class HTMLStream(Stream): + color = { + DEBUG: '', + INFO:'', + WARN: '', + ERROR: '' + } + normal = '' + def __init__(self, stream=sys.stdout): Stream.__init__(self, stream) - self.color = { - DEBUG: '', - INFO:'', - WARN: '', - ERROR: '' - } - self.normal = '' def prints(self, level, *args, **kwargs): self.stream.write(self.color[level]) @@ -82,6 +83,43 @@ class HTMLStream(Stream): def flush(self): self.stream.flush() +class UnicodeHTMLStream(HTMLStream): + + def __init__(self): + self.clear() + + def flush(self): + pass + + def prints(self, level, *args, **kwargs): + col = self.color[level] + if col != self.last_col: + if self.data: + self.data.append(self.normal) + self.data.append(col) + self.last_col = col + + sep = kwargs.get(u'sep', u' ') + end = kwargs.get(u'end', u'\n') + + for arg in args: + if isbytestring(arg): + arg = force_unicode(arg) + elif not isinstance(arg, unicode): + arg = as_unicode(arg) + self.data.append(arg+sep) + self.data.append(end) + + def clear(self): + self.data = [] + self.last_col = self.color[INFO] + + @property + def html(self): + end = self.normal if self.data else u'' + return u''.join(self.data) + end + + class Log(object): DEBUG = DEBUG