diff --git a/src/calibre/ebooks/metadata/sources/identify.py b/src/calibre/ebooks/metadata/sources/identify.py
index 075c780596..85549904e7 100644
--- a/src/calibre/ebooks/metadata/sources/identify.py
+++ b/src/calibre/ebooks/metadata/sources/identify.py
@@ -217,6 +217,10 @@ class ISBNMerge(object):
for r in results:
ans.identifiers.update(r.identifiers)
+ # Cover URL
+ ans.has_cached_cover_url = bool([r for r in results if
+ getattr(r, 'has_cached_cover_url', False)])
+
# Merge any other fields with no special handling (random merge)
touched_fields = set()
for r in results:
diff --git a/src/calibre/gui2/metadata/single_download.py b/src/calibre/gui2/metadata/single_download.py
index 19e92adf4f..94ee8f8a13 100644
--- a/src/calibre/gui2/metadata/single_download.py
+++ b/src/calibre/gui2/metadata/single_download.py
@@ -12,14 +12,16 @@ 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,
- QTimer, pyqtSignal)
+ QTimer, pyqtSignal, QAbstractTableModel, QVariant, QSize)
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 GUILog as Log
from calibre.ebooks.metadata.sources.identify import identify
-from calibre.gui2 import error_dialog
+from calibre.ebooks.metadata.book.base import Metadata
+from calibre.gui2 import error_dialog, NONE
+from calibre.utils.date import utcnow, fromordinal, format_date
class RichTextDelegate(QStyledItemDelegate): # {{{
@@ -49,10 +51,85 @@ class RichTextDelegate(QStyledItemDelegate): # {{{
painter.restore()
# }}}
+class ResultsModel(QAbstractTableModel):
+
+ COLUMNS = (
+ '#', _('Title'), _('Published'), _('Has cover'), _('Has summary')
+ )
+ HTML_COLS = (1, 2)
+ ICON_COLS = (3, 4)
+
+ def __init__(self, results, parent=None):
+ QAbstractTableModel.__init__(self, parent)
+ self.results = results
+ self.yes_icon = QVariant(QIcon(I('ok.png')))
+
+ def rowCount(self, parent=None):
+ return len(self.results)
+
+ def columnCount(self, parent=None):
+ return len(self.COLUMNS)
+
+ def headerData(self, section, orientation, role):
+ if role != Qt.DisplayRole:
+ return NONE
+ if orientation == Qt.Horizontal:
+ try:
+ return QVariant(self.COLUMNS[section])
+ except:
+ return NONE
+ else:
+ return QVariant(unicode(section+1))
+
+ def data_as_text(self, book, col):
+ if col == 0:
+ return unicode(book.gui_rank+1)
+ if col == 1:
+ t = book.title if book.title else _('Unknown')
+ a = authors_to_string(book.authors) if book.authors else ''
+ return '%s
%s' % (t, a)
+ if col == 2:
+ d = format_date(book.pubdate, 'yyyy') if book.pubdate else _('Unknown')
+ p = book.publisher if book.publisher else ''
+ return '%s
%s' % (d, p)
+
+
+ def data(self, index, role):
+ row, col = index.row(), index.column()
+ try:
+ book = self.results[row]
+ except:
+ return NONE
+ if role == Qt.DisplayRole and col not in self.ICON_COLS:
+ res = self.data_as_text(book, col)
+ if res:
+ return QVariant(res)
+ return NONE
+ elif role == Qt.DecorationRole and col in self.ICON_COLS:
+ if col == 3 and getattr(book, 'has_cached_cover_url', False):
+ return self.yes_icon
+ if col == 4 and book.comments:
+ return self.yes_icon
+ return NONE
+
class ResultsView(QTableView): # {{{
def __init__(self, parent=None):
QTableView.__init__(self, parent)
+ self.rt_delegate = RichTextDelegate(self)
+ self.setSelectionMode(self.SingleSelection)
+ self.setAlternatingRowColors(True)
+ self.setSelectionBehavior(self.SelectRows)
+ self.setIconSize(QSize(24, 24))
+
+ def show_results(self, results):
+ self._model = ResultsModel(results, self)
+ self.setModel(self._model)
+ for i in self._model.HTML_COLS:
+ self.setItemDelegateForColumn(i, self.rt_delegate)
+ self.resizeRowsToContents()
+ self.resizeColumnsToContents()
+
# }}}
class Comments(QWebView): # {{{
@@ -60,8 +137,8 @@ class Comments(QWebView): # {{{
def __init__(self, parent=None):
QWebView.__init__(self, parent)
self.setAcceptDrops(False)
- self.setMaximumWidth(270)
- self.setMinimumWidth(270)
+ self.setMaximumWidth(300)
+ self.setMinimumWidth(300)
palette = self.palette()
palette.setBrush(QPalette.Base, Qt.transparent)
@@ -116,10 +193,30 @@ class IdentifyWorker(Thread): # {{{
self.results = []
self.error = None
+ def sample_results(self):
+ m1 = Metadata('The Great Gatsby', ['Francis Scott Fitzgerald'])
+ m2 = Metadata('The Great Gatsby', ['F. Scott Fitzgerald'])
+ m1.has_cached_cover_url = True
+ m2.has_cached_cover_url = False
+ m1.comments = 'Some comments '*10
+ m1.tags = ['tag%d'%i for i in range(20)]
+ m1.rating = 4.4
+ m1.language = 'en'
+ m2.language = 'fr'
+ m1.pubdate = utcnow()
+ m2.pubdate = fromordinal(1000000)
+ m1.publisher = 'Publisher 1'
+ m2.publisher = 'Publisher 2'
+
+ return [m1, m2]
+
def run(self):
try:
- self.results = identify(self.log, self.abort, title=self.title,
- authors=self.authors, identifiers=self.identifiers)
+ if True:
+ self.results = self.sample_results()
+ else:
+ 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:
@@ -194,22 +291,22 @@ class IdentifyWidget(QWidget): # {{{
self.worker = IdentifyWorker(self.log, self.abort, title,
authors, identifiers)
- # self.worker.start()
+ self.worker.start()
QTimer.singleShot(50, self.update)
def update(self):
if self.worker.is_alive():
QTimer.singleShot(50, self.update)
- return
- self.process_results()
+ else:
+ self.process_results()
def process_results(self):
if self.worker.error is not None:
error_dialog(self, _('Download failed'),
_('Failed to download metadata. Click '
'Show Details to see details'),
- show=True, det_msg=self.wroker.error)
+ show=True, det_msg=self.worker.error)
self.rejected.emit()
return
@@ -225,6 +322,8 @@ class IdentifyWidget(QWidget): # {{{
self.rejected.emit()
return
+ self.results_view.show_results(self.worker.results)
+
def cancel(self):
self.abort.set()