diff --git a/src/calibre/gui2/metadata/single_download.py b/src/calibre/gui2/metadata/single_download.py
index eb067e1211..79a1db131b 100644
--- a/src/calibre/gui2/metadata/single_download.py
+++ b/src/calibre/gui2/metadata/single_download.py
@@ -8,6 +8,7 @@
__docformat__ = 'restructuredtext en'
from threading import Thread, Event
+from operator import attrgetter
from PyQt4.Qt import (QStyledItemDelegate, QTextDocument, QRectF, QIcon, Qt,
QStyle, QApplication, QDialog, QVBoxLayout, QLabel, QDialogButtonBox,
@@ -22,7 +23,7 @@
from calibre.ebooks.metadata.book.base import Metadata
from calibre.gui2 import error_dialog, NONE
from calibre.utils.date import utcnow, fromordinal, format_date
-
+from calibre.library.comments import comments_to_html
class RichTextDelegate(QStyledItemDelegate): # {{{
@@ -107,10 +108,33 @@ def data(self, index, role):
return self.yes_icon
if col == 4 and book.comments:
return self.yes_icon
+ elif role == Qt.UserRole:
+ return book
return NONE
+ def sort(self, col, order=Qt.AscendingOrder):
+ key = lambda x: x
+ if col == 0:
+ key = attrgetter('gui_rank')
+ elif col == 1:
+ key = attrgetter('title')
+ elif col == 2:
+ key = attrgetter('authors')
+ elif col == 3:
+ key = attrgetter('has_cached_cover_url')
+ elif key == 4:
+ key = lambda x: bool(x.comments)
+
+ self.results.sort(key=key, reverse=order==Qt.AscendingOrder)
+ self.reset()
+
+
+
class ResultsView(QTableView): # {{{
+ show_details_signal = pyqtSignal(object)
+ book_selected = pyqtSignal(object)
+
def __init__(self, parent=None):
QTableView.__init__(self, parent)
self.rt_delegate = RichTextDelegate(self)
@@ -118,6 +142,9 @@ def __init__(self, parent=None):
self.setAlternatingRowColors(True)
self.setSelectionBehavior(self.SelectRows)
self.setIconSize(QSize(24, 24))
+ self.clicked.connect(self.show_details)
+ self.doubleClicked.connect(self.select_index)
+ self.setSortingEnabled(True)
def show_results(self, results):
self._model = ResultsModel(results, self)
@@ -126,6 +153,38 @@ def show_results(self, results):
self.setItemDelegateForColumn(i, self.rt_delegate)
self.resizeRowsToContents()
self.resizeColumnsToContents()
+ self.setFocus(Qt.OtherFocusReason)
+
+ def currentChanged(self, current, previous):
+ ret = QTableView.currentChanged(self, current, previous)
+ self.show_details(current)
+ return ret
+
+ def show_details(self, index):
+ book = self.model().data(index, Qt.UserRole)
+ parts = [
+ '
',
+ '%s
'%book.title,
+ '%s
'%authors_to_string(book.authors),
+ ]
+ if not book.is_null('rating'):
+ parts.append('%s
'%('\u2605'*int(book.rating)))
+ parts.append('')
+ if book.tags:
+ parts.append('%s
\u00a0
'%', '.join(book.tags))
+ if book.comments:
+ parts.append(comments_to_html(book.comments))
+
+ self.show_details_signal.emit(''.join(parts))
+
+ def select_index(self, index):
+ if not index.isValid():
+ index = self.model().index(0, 0)
+ book = self.model().data(index, Qt.UserRole)
+ self.book_selected.emit(book)
+
+ def get_result(self):
+ self.select_index(self.currentIndex())
# }}}
@@ -224,6 +283,8 @@ def run(self):
class IdentifyWidget(QWidget): # {{{
rejected = pyqtSignal()
+ results_found = pyqtSignal()
+ book_selected = pyqtSignal(object)
def __init__(self, log, parent=None):
QWidget.__init__(self, parent)
@@ -241,11 +302,15 @@ def __init__(self, log, parent=None):
l.addWidget(self.top, 0, 0)
self.results_view = ResultsView(self)
+ self.results_view.book_selected.connect(self.book_selected.emit)
+ self.get_result = self.results_view.get_result
l.addWidget(self.results_view, 1, 0)
self.comments_view = Comments(self)
l.addWidget(self.comments_view, 1, 1)
+ self.results_view.show_details_signal.connect(self.comments_view.show_data)
+
self.query = QLabel('download starting...')
f = self.query.font()
f.setPointSize(f.pointSize()-2)
@@ -326,6 +391,8 @@ def process_results(self):
To see details, click on any result
''' %
len(self.worker.results))
+ self.results_found.emit()
+
def cancel(self):
self.abort.set()
@@ -345,23 +412,46 @@ def __init__(self, log, parent=None):
self.setLayout(l)
l.addWidget(self.stack)
- self.bb = QDialogButtonBox(QDialogButtonBox.Cancel)
+ self.bb = QDialogButtonBox(QDialogButtonBox.Cancel|QDialogButtonBox.Ok)
l.addWidget(self.bb)
self.bb.rejected.connect(self.reject)
+ self.next_button = self.bb.addButton(_('Next'), self.bb.AcceptRole)
+ self.next_button.setDefault(True)
+ self.next_button.setEnabled(False)
+ self.next_button.clicked.connect(self.next_clicked)
+ self.ok_button = self.bb.button(self.bb.Ok)
+ self.ok_button.setVisible(False)
+ self.ok_button.clicked.connect(self.ok_clicked)
self.identify_widget = IdentifyWidget(log, self)
self.identify_widget.rejected.connect(self.reject)
+ self.identify_widget.results_found.connect(self.identify_results_found)
+ self.identify_widget.book_selected.connect(self.book_selected)
self.stack.addWidget(self.identify_widget)
self.resize(850, 500)
+ def book_selected(self, book):
+ print (book)
+ self.next_button.setVisible(False)
+ self.ok_button.setVisible(True)
+
def accept(self):
- # Prevent pressing Enter from closing the dialog
+ # Prevent the usual dialog accept mechanisms from working
pass
def reject(self):
self.identify_widget.cancel()
return QDialog.reject(self)
+ def identify_results_found(self):
+ self.next_button.setEnabled(True)
+
+ def next_clicked(self, *args):
+ self.identify_widget.get_result()
+
+ def ok_clicked(self, *args):
+ pass
+
def start(self, title=None, authors=None, identifiers={}):
self.identify_widget.start(title=title, authors=authors,
identifiers=identifiers)