diff --git a/src/calibre/gui2/actions/edit_metadata.py b/src/calibre/gui2/actions/edit_metadata.py index c2558d56ae..26d15d0a83 100644 --- a/src/calibre/gui2/actions/edit_metadata.py +++ b/src/calibre/gui2/actions/edit_metadata.py @@ -80,7 +80,7 @@ class EditMetadataAction(InterfaceAction): Dispatcher(self.metadata_downloaded), ensure_fields=ensure_fields) - def cleanup_bulk_download(self, tdir): + def cleanup_bulk_download(self, tdir, *args): try: shutil.rmtree(tdir, ignore_errors=True) except: @@ -108,22 +108,26 @@ class EditMetadataAction(InterfaceAction): 'Proceed with updating the metadata in your library?')%len(id_map) show_copy_button = False + checkbox_msg = None if failed_ids or failed_covers: show_copy_button = True num = len(failed_ids.union(failed_covers)) msg += '

'+_('Could not download metadata and/or covers for %d of the books. Click' ' "Show details" to see which books.')%num + checkbox_msg = _('Show the &failed books in the main book list ' + 'after updating metadata') - payload = (id_map, tdir, log_file, lm_map) - self.gui.proceed_question(self.apply_downloaded_metadata, - payload, log_file, - _('Download log'), _('Download complete'), msg, + payload = (id_map, tdir, log_file, lm_map, + failed_ids.union(failed_covers)) + self.gui.proceed_question(self.apply_downloaded_metadata, payload, + log_file, _('Download log'), _('Download complete'), msg, det_msg=det_msg, show_copy_button=show_copy_button, - cancel_callback=lambda x:self.cleanup_bulk_download(tdir), - log_is_file=True) + cancel_callback=partial(self.cleanup_bulk_download, tdir), + log_is_file=True, checkbox_msg=checkbox_msg, + checkbox_checked=False) - def apply_downloaded_metadata(self, payload): - good_ids, tdir, log_file, lm_map = payload + def apply_downloaded_metadata(self, payload, *args): + good_ids, tdir, log_file, lm_map, failed_ids = payload if not good_ids: return @@ -162,8 +166,18 @@ class EditMetadataAction(InterfaceAction): cov = None id_map[bid] = (opf, cov) - self.apply_metadata_changes(id_map, callback=lambda x: - self.cleanup_bulk_download(tdir)) + restrict_to_failed = bool(args and args[0]) + if restrict_to_failed: + db.data.set_marked_ids(failed_ids) + + self.apply_metadata_changes(id_map, + callback=partial(self.downloaded_metadata_applied, tdir, + restrict_to_failed)) + + def downloaded_metadata_applied(self, tdir, restrict_to_failed, *args): + if restrict_to_failed: + self.gui.search.set_search_string('marked:true') + self.cleanup_bulk_download(tdir) # }}} diff --git a/src/calibre/gui2/proceed.py b/src/calibre/gui2/proceed.py index 1074792096..9bdf48e086 100644 --- a/src/calibre/gui2/proceed.py +++ b/src/calibre/gui2/proceed.py @@ -11,18 +11,18 @@ from collections import namedtuple from PyQt4.Qt import (QDialog, Qt, QLabel, QGridLayout, QPixmap, QDialogButtonBox, QApplication, QSize, pyqtSignal, QIcon, - QPlainTextEdit) + QPlainTextEdit, QCheckBox) from calibre.constants import __version__ from calibre.gui2.dialogs.message_box import ViewLog Question = namedtuple('Question', 'payload callback cancel_callback ' 'title msg html_log log_viewer_title log_is_file det_msg ' - 'show_copy_button') + 'show_copy_button checkbox_msg checkbox_checked') class ProceedQuestion(QDialog): - ask_question = pyqtSignal(object, object) + ask_question = pyqtSignal(object, object, object) def __init__(self, parent): QDialog.__init__(self, parent) @@ -62,10 +62,13 @@ class ProceedQuestion(QDialog): self.bb.setStandardButtons(self.bb.Yes|self.bb.No) self.bb.button(self.bb.Yes).setDefault(True) + self.checkbox = QCheckBox('', self) + l.addWidget(ic, 0, 0, 1, 1) l.addWidget(msg, 0, 1, 1, 1) - l.addWidget(self.det_msg, 1, 0, 1, 2) - l.addWidget(self.bb, 2, 0, 1, 2) + l.addWidget(self.checkbox, 1, 0, 1, 2) + l.addWidget(self.det_msg, 2, 0, 1, 2) + l.addWidget(self.bb, 3, 0, 1, 2) self.ask_question.connect(self.do_ask_question, type=Qt.QueuedConnection) @@ -82,19 +85,28 @@ class ProceedQuestion(QDialog): if self.questions: payload, callback, cancel_callback = self.questions[0][:3] self.questions = self.questions[1:] - self.ask_question.emit(callback, payload) + cb = None + if self.checkbox.isVisible(): + cb = bool(self.checkbox.isChecked()) + self.ask_question.emit(callback, payload, cb) self.hide() def reject(self): if self.questions: payload, callback, cancel_callback = self.questions[0][:3] self.questions = self.questions[1:] - self.ask_question.emit(cancel_callback, payload) + cb = None + if self.checkbox.isVisible(): + cb = bool(self.checkbox.isChecked()) + self.ask_question.emit(cancel_callback, payload, cb) self.hide() - def do_ask_question(self, callback, payload): + def do_ask_question(self, callback, payload, checkbox_checked): if callable(callback): - callback(payload) + args = [payload] + if checkbox_checked is not None: + args.append(checkbox_checked) + callback(*args) self.show_question() def toggle_det_msg(self, *args): @@ -122,6 +134,10 @@ class ProceedQuestion(QDialog): self.det_msg.setVisible(False) self.det_msg_toggle.setVisible(bool(question.det_msg)) self.det_msg_toggle.setText(self.show_det_msg) + self.checkbox.setVisible(question.checkbox_msg is not None) + if question.checkbox_msg is not None: + self.checkbox.setText(question.checkbox_msg) + self.checkbox.setChecked(question.checkbox_checked) self.do_resize() self.show() self.bb.button(self.bb.Yes).setDefault(True) @@ -129,10 +145,10 @@ class ProceedQuestion(QDialog): def __call__(self, callback, payload, html_log, log_viewer_title, title, msg, det_msg='', show_copy_button=False, cancel_callback=None, - log_is_file=False): + log_is_file=False, checkbox_msg=None, checkbox_checked=False): ''' A non modal popup that notifies the user that a background task has - been completed. This class guarantees that onlya single popup is + been completed. This class guarantees that only a single popup is visible at any one time. Other requests are queued and displayed after the user dismisses the current popup. @@ -147,11 +163,18 @@ class ProceedQuestion(QDialog): :param msg: The msg to display :param det_msg: Detailed message :param log_is_file: If True the html_log parameter is interpreted as - the path to a file on disk containing the log encoded with utf-8 + the path to a file on disk containing the log + encoded with utf-8 + :param checkbox_msg: If not None, a checkbox is displayed in the + dialog, showing this message. The callback is + called with both the payload and the state of the + checkbox as arguments. + :param checkbox_checked: If True the checkbox is checked by default. + ''' question = Question(payload, callback, cancel_callback, title, msg, html_log, log_viewer_title, log_is_file, det_msg, - show_copy_button) + show_copy_button, checkbox_msg, checkbox_checked) self.questions.append(question) self.show_question() @@ -169,7 +192,8 @@ def main(): from calibre.gui2 import Application app = Application([]) p = ProceedQuestion(None) - p(lambda p:None, None, 'ass', 'ass', 'testing', 'testing') + p(lambda p:None, None, 'ass', 'ass', 'testing', 'testing', + checkbox_msg='testing the ruddy checkbox', det_msg='details') p.exec_() app