diff --git a/src/calibre/gui2/tweak_book/boss.py b/src/calibre/gui2/tweak_book/boss.py index ce1a2b72fc..5cfbbd3d54 100644 --- a/src/calibre/gui2/tweak_book/boss.py +++ b/src/calibre/gui2/tweak_book/boss.py @@ -23,12 +23,12 @@ from calibre.ebooks.oeb.polish.cover import mark_as_cover, mark_as_titlepage from calibre.ebooks.oeb.polish.pretty import fix_all_html, pretty_all from calibre.ebooks.oeb.polish.replace import rename_files from calibre.ebooks.oeb.polish.split import split, merge, AbortError -from calibre.gui2 import error_dialog, choose_files, question_dialog, info_dialog +from calibre.gui2 import error_dialog, choose_files, question_dialog, info_dialog, choose_save_file from calibre.gui2.dialogs.confirm_delete import confirm from calibre.gui2.tweak_book import set_current_container, current_container, tprefs, actions, editors from calibre.gui2.tweak_book.undo import GlobalUndoHistory from calibre.gui2.tweak_book.file_list import NewFileDialog -from calibre.gui2.tweak_book.save import SaveManager +from calibre.gui2.tweak_book.save import SaveManager, save_container from calibre.gui2.tweak_book.preview import parse_worker, font_cache from calibre.gui2.tweak_book.toc import TOCEditor from calibre.gui2.tweak_book.editor import editor_from_syntax, syntax_from_mime @@ -581,6 +581,35 @@ class Boss(QObject): container = clone_container(c, tdir) self.save_manager.schedule(tdir, container) + def save_copy(self): + c = current_container() + ext = c.path_to_ebook.rpartition('.')[-1] + path = choose_save_file(self.gui, 'tweak_book_save_copy', _( + 'Choose path'), filters=[(_('Book (%s)') % ext.upper(), [ext.lower()])], all_files=False) + if not path: + return + tdir = self.mkdtemp(prefix='save-copy-') + container = clone_container(c, tdir) + for name, ed in editors.iteritems(): + if ed.is_modified: + with c.open(name, 'wb') as f: + f.write(ed.data) + + def do_save(c, path, tdir): + save_container(c, path) + shutil.rmtree(tdir, ignore_errors=True) + return path + + self.gui.blocking_job('save_copy', _('Saving copy, please wait...'), self.copy_saved, do_save, container, path, tdir) + + def copy_saved(self, job): + if job.traceback is not None: + return error_dialog(self.gui, _('Failed to save copy'), + _('Failed to save copy, click Show details for more information.'), det_msg=job.traceback, show=True) + msg = _('Copy saved to %s') % job.result + info_dialog(self.gui, _('Copy saved'), msg, show=True) + self.gui.show_status_message(msg, 5) + def report_save_error(self, tb): if self.doing_terminal_save: prints(tb, file=sys.stderr) diff --git a/src/calibre/gui2/tweak_book/save.py b/src/calibre/gui2/tweak_book/save.py index d1b2680ac5..508b8673fd 100644 --- a/src/calibre/gui2/tweak_book/save.py +++ b/src/calibre/gui2/tweak_book/save.py @@ -18,6 +18,18 @@ from calibre.gui2.progress_indicator import ProgressIndicator from calibre.utils import join_with_timeout from calibre.utils.filenames import atomic_rename +def save_container(container, path): + temp = PersistentTemporaryFile( + prefix=('_' if iswindows else '.'), suffix=os.path.splitext(path)[1], dir=os.path.dirname(path)) + temp.close() + temp = temp.name + try: + container.commit(temp) + atomic_rename(temp, path) + finally: + if os.path.exists(temp): + os.remove(temp) + class SaveWidget(QWidget): def __init__(self, parent=None): @@ -105,18 +117,9 @@ class SaveManager(QObject): self.save_done.emit() def do_save(self, tdir, container): - temp = None try: - path = container.path_to_ebook - temp = PersistentTemporaryFile( - prefix=('_' if iswindows else '.'), suffix=os.path.splitext(path)[1], dir=os.path.dirname(path)) - temp.close() - temp = temp.name - container.commit(temp) - atomic_rename(temp, path) + save_container(container, container.path_to_ebook) finally: - if temp and os.path.exists(temp): - os.remove(temp) shutil.rmtree(tdir, ignore_errors=True) @property diff --git a/src/calibre/gui2/tweak_book/ui.py b/src/calibre/gui2/tweak_book/ui.py index 1e21e142c9..aa4d79d788 100644 --- a/src/calibre/gui2/tweak_book/ui.py +++ b/src/calibre/gui2/tweak_book/ui.py @@ -155,6 +155,9 @@ class Main(MainWindow): self.keyboard.finalize() + def show_status_message(self, msg, timeout=5): + self.status_bar.showMessage(msg, int(timeout*1000)) + def elided_text(self, text, width=200, mode=Qt.ElideMiddle): return elided_text(self.font(), text, width=width, mode=mode) @@ -185,6 +188,7 @@ class Main(MainWindow): _('Revert book state to after the next action (Redo)')) self.action_save = reg('save.png', _('&Save'), self.boss.save_book, 'save-book', 'Ctrl+Shift+S', _('Save book')) self.action_save.setEnabled(False) + self.action_save_copy = reg('save.png', _('Save a ©'), self.boss.save_copy, 'save-copy', 'Ctrl+Alt+S', _('Save a copy of the book')) self.action_quit = reg('quit.png', _('&Quit'), self.boss.quit, 'quit', 'Ctrl+Q', _('Quit')) self.action_preferences = reg('config.png', _('&Preferences'), self.boss.preferences, 'preferences', 'Ctrl+P', _('Preferences')) @@ -279,7 +283,10 @@ class Main(MainWindow): f = b.addMenu(_('&File')) f.addAction(self.action_new_file) f.addAction(self.action_open_book) + f.addSeparator() f.addAction(self.action_save) + f.addAction(self.action_save_copy) + f.addSeparator() f.addAction(self.action_quit) e = b.addMenu(_('&Edit'))