From 20d20d0b7fbae32ca8cbd80533ed220e8d4a11ca Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 15 Jul 2011 19:29:48 -0600 Subject: [PATCH] When calibre does a conversion from the same format to the same format, for example, from EPUB to EPUB, the original file is saved, so that in case the conversion is poor, you can tweak the settings and run it again. The orignal is automatically used every time you re-run the conversion. If you want the old behavior, there is a tweak that prevents calibre from saving the originals in Preferences->Tweaks. --- resources/default_tweaks.py | 7 +++++++ src/calibre/ebooks/conversion/plumber.py | 2 +- src/calibre/ebooks/oeb/iterator.py | 2 +- src/calibre/gui2/actions/convert.py | 13 ++++++++++--- src/calibre/gui2/actions/view.py | 3 ++- src/calibre/gui2/tools.py | 18 ++++++++++++++---- src/calibre/gui2/viewer/main.py | 13 +++++++------ src/calibre/library/database2.py | 17 +++++++++++++++++ 8 files changed, 59 insertions(+), 16 deletions(-) diff --git a/resources/default_tweaks.py b/resources/default_tweaks.py index 861e1bf70c..3e2cc4da57 100644 --- a/resources/default_tweaks.py +++ b/resources/default_tweaks.py @@ -366,3 +366,10 @@ server_listen_on = '0.0.0.0' # on at your own risk! unified_title_toolbar_on_osx = False +#: Save original file when converting from same format to same format +# When calibre does a conversion from the same format to the same format, for +# example, from EPUB to EPUB, the original file is saved, so that in case the +# conversion is poor, you can tweak the settings and run it again. By setting +# this to False you can prevent calibre from saving the original file. +save_original_format = True + diff --git a/src/calibre/ebooks/conversion/plumber.py b/src/calibre/ebooks/conversion/plumber.py index d0d427bf74..31f125dd88 100644 --- a/src/calibre/ebooks/conversion/plumber.py +++ b/src/calibre/ebooks/conversion/plumber.py @@ -602,7 +602,7 @@ OptionRecommendation(name='sr3_replace', input_fmt = os.path.splitext(self.input)[1] if not input_fmt: raise ValueError('Input file must have an extension') - input_fmt = input_fmt[1:].lower() + input_fmt = input_fmt[1:].lower().replace('original_', '') self.archive_input_tdir = None if input_fmt in ARCHIVE_FMTS: self.log('Processing archive...') diff --git a/src/calibre/ebooks/oeb/iterator.py b/src/calibre/ebooks/oeb/iterator.py index 92a4febb6c..e584acc392 100644 --- a/src/calibre/ebooks/oeb/iterator.py +++ b/src/calibre/ebooks/oeb/iterator.py @@ -92,7 +92,7 @@ class EbookIterator(object): self.config = DynamicConfig(name='iterator') ext = os.path.splitext(pathtoebook)[1].replace('.', '').lower() ext = re.sub(r'(x{0,1})htm(l{0,1})', 'html', ext) - self.ebook_ext = ext + self.ebook_ext = ext.replace('original_', '') def search(self, text, index, backwards=False): text = text.lower() diff --git a/src/calibre/gui2/actions/convert.py b/src/calibre/gui2/actions/convert.py index 17fa0ad622..e3dc697a45 100644 --- a/src/calibre/gui2/actions/convert.py +++ b/src/calibre/gui2/actions/convert.py @@ -12,7 +12,7 @@ from PyQt4.Qt import QModelIndex, QMenu from calibre.gui2 import error_dialog, Dispatcher from calibre.gui2.tools import convert_single_ebook, convert_bulk_ebook -from calibre.utils.config import prefs +from calibre.utils.config import prefs, tweaks from calibre.gui2.actions import InterfaceAction from calibre.customize.ui import plugin_for_input_format @@ -118,6 +118,8 @@ class ConvertAction(InterfaceAction): def queue_convert_jobs(self, jobs, changed, bad, rows, previous, converted_func, extra_job_args=[]): for func, args, desc, fmt, id, temp_files in jobs: + func, _, same_fmt = func.partition(':') + same_fmt = same_fmt == 'same_fmt' input_file = args[0] input_fmt = os.path.splitext(input_file)[1] core_usage = 1 @@ -131,6 +133,7 @@ class ConvertAction(InterfaceAction): job = self.gui.job_manager.run_job(Dispatcher(converted_func), func, args=args, description=desc, core_usage=core_usage) + job.conversion_of_same_fmt = same_fmt args = [temp_files, fmt, id]+extra_job_args self.conversion_jobs[job] = tuple(args) @@ -166,14 +169,18 @@ class ConvertAction(InterfaceAction): if job.failed: self.gui.job_exception(job) return + same_fmt = getattr(job, 'conversion_of_same_fmt', False) fmtf = temp_files[-1].name if os.stat(fmtf).st_size < 1: raise Exception(_('Empty output file, ' 'probably the conversion process crashed')) + db = self.gui.current_db + if same_fmt and tweaks['save_original_format']: + db.save_original_format(book_id, fmt, notify=False) + with open(temp_files[-1].name, 'rb') as data: - self.gui.library_view.model().db.add_format(book_id, \ - fmt, data, index_is_id=True) + db.add_format(book_id, fmt, data, index_is_id=True) self.gui.status_bar.show_message(job.description + \ (' completed'), 2000) finally: diff --git a/src/calibre/gui2/actions/view.py b/src/calibre/gui2/actions/view.py index 6cf5c5d5af..a877a8f75f 100644 --- a/src/calibre/gui2/actions/view.py +++ b/src/calibre/gui2/actions/view.py @@ -128,7 +128,8 @@ class ViewAction(InterfaceAction): self.gui.unsetCursor() def _view_file(self, name): - ext = os.path.splitext(name)[1].upper().replace('.', '') + ext = os.path.splitext(name)[1].upper().replace('.', + '').replace('ORIGINAL_', '') viewer = 'lrfviewer' if ext == 'LRF' else 'ebook-viewer' internal = ext in config['internally_viewed_formats'] self._launch_viewer(name, viewer, internal) diff --git a/src/calibre/gui2/tools.py b/src/calibre/gui2/tools.py index 1726c791f0..021617aa4a 100644 --- a/src/calibre/gui2/tools.py +++ b/src/calibre/gui2/tools.py @@ -53,7 +53,9 @@ def convert_single_ebook(parent, db, book_ids, auto_conversion=False, # {{{ mi = db.get_metadata(book_id, True) in_file = PersistentTemporaryFile('.'+d.input_format) with in_file: - db.copy_format_to(book_id, d.input_format, in_file, + input_fmt = db.original_fmt(book_id, d.input_format).lower() + same_fmt = input_fmt == d.output_format.lower() + db.copy_format_to(book_id, input_fmt, in_file, index_is_id=True) out_file = PersistentTemporaryFile('.' + d.output_format) @@ -79,7 +81,10 @@ def convert_single_ebook(parent, db, book_ids, auto_conversion=False, # {{{ temp_files.append(d.cover_file) args = [in_file.name, out_file.name, recs] temp_files.append(out_file) - jobs.append(('gui_convert_override', args, desc, d.output_format.upper(), book_id, temp_files)) + func = 'gui_convert_override' + if same_fmt: + func += ':same_fmt' + jobs.append((func, args, desc, d.output_format.upper(), book_id, temp_files)) changed = True d.break_cycles() @@ -144,10 +149,12 @@ class QueueBulk(QProgressDialog): try: input_format = get_input_format_for_book(self.db, book_id, None)[0] + input_fmt = self.db.original_fmt(book_id, input_format).lower() + same_fmt = input_fmt == self.output_format.lower() mi, opf_file = create_opf_file(self.db, book_id) in_file = PersistentTemporaryFile('.'+input_format) with in_file: - self.db.copy_format_to(book_id, input_format, in_file, + self.db.copy_format_to(book_id, input_fmt, in_file, index_is_id=True) out_file = PersistentTemporaryFile('.' + self.output_format) @@ -192,7 +199,10 @@ class QueueBulk(QProgressDialog): args = [in_file.name, out_file.name, lrecs] temp_files.append(out_file) - self.jobs.append(('gui_convert_override', args, desc, self.output_format.upper(), book_id, temp_files)) + func = 'gui_convert_override' + if same_fmt: + func += ':same_fmt' + self.jobs.append((func, args, desc, self.output_format.upper(), book_id, temp_files)) self.changed = True self.setValue(self.i) diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index 35b25b262e..5e3d9908c1 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -661,12 +661,13 @@ class EbookViewer(MainWindow, Ui_EbookViewer): def save_current_position(self): if not self.get_remember_current_page_opt(): return - try: - pos = self.view.bookmark() - bookmark = '%d#%s'%(self.current_index, pos) - self.iterator.add_bookmark(('calibre_current_page_bookmark', bookmark)) - except: - traceback.print_exc() + if hasattr(self, 'current_index'): + try: + pos = self.view.bookmark() + bookmark = '%d#%s'%(self.current_index, pos) + self.iterator.add_bookmark(('calibre_current_page_bookmark', bookmark)) + except: + traceback.print_exc() def load_ebook(self, pathtoebook): if self.iterator is not None: diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index ea4ca373c4..8d16ffbc52 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -1312,6 +1312,23 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): self.notify('metadata', [id]) return True + def save_original_format(self, book_id, fmt, notify=True): + fmt = fmt.upper() + if 'ORIGINAL' in fmt: + raise ValueError('Cannot save original of an original fmt') + opath = self.format_abspath(book_id, fmt, index_is_id=True) + if opath is None: + return False + nfmt = 'ORIGINAL_'+fmt + with lopen(opath, 'rb') as f: + return self.add_format(book_id, nfmt, f, index_is_id=True, notify=notify) + + def original_fmt(self, book_id, fmt): + fmt = fmt + nfmt = ('ORIGINAL_%s'%fmt).upper() + opath = self.format_abspath(book_id, nfmt, index_is_id=True) + return fmt if opath is None else nfmt + def delete_book(self, id, notify=True, commit=True, permanent=False): ''' Removes book from the result cache and the underlying database.