diff --git a/src/calibre/gui2/actions/copy_to_library.py b/src/calibre/gui2/actions/copy_to_library.py index a4e5791283..5aca55257b 100644 --- a/src/calibre/gui2/actions/copy_to_library.py +++ b/src/calibre/gui2/actions/copy_to_library.py @@ -98,6 +98,7 @@ class Worker(Thread): # {{{ def __init__(self, ids, db, loc, progress, done, delete_after, add_duplicates): Thread.__init__(self) + self.was_canceled = False self.ids = ids self.processed = set() self.db = db @@ -105,6 +106,7 @@ class Worker(Thread): # {{{ self.error = None self.progress = progress self.done = done + self.left_after_cancel = 0 self.delete_after = delete_after self.auto_merged_ids = {} self.add_duplicates = add_duplicates @@ -112,6 +114,9 @@ class Worker(Thread): # {{{ self.check_for_duplicates = not add_duplicates and (prefs['add_formats_to_existing'] or prefs['check_for_dupes_on_ctl']) self.failed_books = {} + def cancel_processing(self): + self.was_canceled = True + def run(self): try: self.doit() @@ -144,6 +149,9 @@ class Worker(Thread): # {{{ def _doit(self, newdb): for i, x in enumerate(self.ids): + if self.was_canceled: + self.left_after_cancel = len(self.ids) - i + break try: self.do_one(i, x, newdb) except Exception as err: @@ -480,7 +488,7 @@ class CopyToLibraryAction(InterfaceAction): aname = _('Moving to') if delete_after else _('Copying to') dtitle = '%s %s'%(aname, os.path.basename(loc)) self.pd = ProgressDialog(dtitle, min=0, max=len(ids)-1, - parent=self.gui, cancelable=False, icon='lt.png') + parent=self.gui, cancelable=True, icon='lt.png') def progress(idx, title): self.pd.set_msg(title) @@ -489,8 +497,19 @@ class CopyToLibraryAction(InterfaceAction): self.worker = Worker(ids, db, loc, Dispatcher(progress), Dispatcher(self.pd.accept), delete_after, add_duplicates) self.worker.start() + self.pd.canceled_signal.connect(self.worker.cancel_processing) self.pd.exec_() + self.pd.canceled_signal.disconnect() + + if self.worker.left_after_cancel: + msg = _('The copying process was interrupted. {} books were copied.').format(len(self.worker.processed)) + if delete_after: + msg += ' ' + _('No books were deleted from this library.') + msg += ' ' + _('The best way to resume this operation is to re-copy all the books with the option to' + ' "Check for duplicates when Copying to Library" in Preferences->Adding books turned on.') + warning_dialog(self.gui, _('Canceled'), msg, show=True) + return if self.worker.error is not None: e, tb = self.worker.error