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.
This commit is contained in:
Kovid Goyal 2011-07-15 19:29:48 -06:00
parent 97428f93a2
commit 20d20d0b7f
8 changed files with 59 additions and 16 deletions

View File

@ -366,3 +366,10 @@ server_listen_on = '0.0.0.0'
# on at your own risk! # on at your own risk!
unified_title_toolbar_on_osx = False 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

View File

@ -602,7 +602,7 @@ OptionRecommendation(name='sr3_replace',
input_fmt = os.path.splitext(self.input)[1] input_fmt = os.path.splitext(self.input)[1]
if not input_fmt: if not input_fmt:
raise ValueError('Input file must have an extension') 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 self.archive_input_tdir = None
if input_fmt in ARCHIVE_FMTS: if input_fmt in ARCHIVE_FMTS:
self.log('Processing archive...') self.log('Processing archive...')

View File

@ -92,7 +92,7 @@ class EbookIterator(object):
self.config = DynamicConfig(name='iterator') self.config = DynamicConfig(name='iterator')
ext = os.path.splitext(pathtoebook)[1].replace('.', '').lower() ext = os.path.splitext(pathtoebook)[1].replace('.', '').lower()
ext = re.sub(r'(x{0,1})htm(l{0,1})', 'html', ext) 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): def search(self, text, index, backwards=False):
text = text.lower() text = text.lower()

View File

@ -12,7 +12,7 @@ from PyQt4.Qt import QModelIndex, QMenu
from calibre.gui2 import error_dialog, Dispatcher from calibre.gui2 import error_dialog, Dispatcher
from calibre.gui2.tools import convert_single_ebook, convert_bulk_ebook 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.gui2.actions import InterfaceAction
from calibre.customize.ui import plugin_for_input_format 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, def queue_convert_jobs(self, jobs, changed, bad, rows, previous,
converted_func, extra_job_args=[]): converted_func, extra_job_args=[]):
for func, args, desc, fmt, id, temp_files in jobs: 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_file = args[0]
input_fmt = os.path.splitext(input_file)[1] input_fmt = os.path.splitext(input_file)[1]
core_usage = 1 core_usage = 1
@ -131,6 +133,7 @@ class ConvertAction(InterfaceAction):
job = self.gui.job_manager.run_job(Dispatcher(converted_func), job = self.gui.job_manager.run_job(Dispatcher(converted_func),
func, args=args, description=desc, func, args=args, description=desc,
core_usage=core_usage) core_usage=core_usage)
job.conversion_of_same_fmt = same_fmt
args = [temp_files, fmt, id]+extra_job_args args = [temp_files, fmt, id]+extra_job_args
self.conversion_jobs[job] = tuple(args) self.conversion_jobs[job] = tuple(args)
@ -166,14 +169,18 @@ class ConvertAction(InterfaceAction):
if job.failed: if job.failed:
self.gui.job_exception(job) self.gui.job_exception(job)
return return
same_fmt = getattr(job, 'conversion_of_same_fmt', False)
fmtf = temp_files[-1].name fmtf = temp_files[-1].name
if os.stat(fmtf).st_size < 1: if os.stat(fmtf).st_size < 1:
raise Exception(_('Empty output file, ' raise Exception(_('Empty output file, '
'probably the conversion process crashed')) '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: with open(temp_files[-1].name, 'rb') as data:
self.gui.library_view.model().db.add_format(book_id, \ db.add_format(book_id, fmt, data, index_is_id=True)
fmt, data, index_is_id=True)
self.gui.status_bar.show_message(job.description + \ self.gui.status_bar.show_message(job.description + \
(' completed'), 2000) (' completed'), 2000)
finally: finally:

View File

@ -128,7 +128,8 @@ class ViewAction(InterfaceAction):
self.gui.unsetCursor() self.gui.unsetCursor()
def _view_file(self, name): 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' viewer = 'lrfviewer' if ext == 'LRF' else 'ebook-viewer'
internal = ext in config['internally_viewed_formats'] internal = ext in config['internally_viewed_formats']
self._launch_viewer(name, viewer, internal) self._launch_viewer(name, viewer, internal)

View File

@ -53,7 +53,9 @@ def convert_single_ebook(parent, db, book_ids, auto_conversion=False, # {{{
mi = db.get_metadata(book_id, True) mi = db.get_metadata(book_id, True)
in_file = PersistentTemporaryFile('.'+d.input_format) in_file = PersistentTemporaryFile('.'+d.input_format)
with in_file: 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) index_is_id=True)
out_file = PersistentTemporaryFile('.' + d.output_format) 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) temp_files.append(d.cover_file)
args = [in_file.name, out_file.name, recs] args = [in_file.name, out_file.name, recs]
temp_files.append(out_file) 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 changed = True
d.break_cycles() d.break_cycles()
@ -144,10 +149,12 @@ class QueueBulk(QProgressDialog):
try: try:
input_format = get_input_format_for_book(self.db, book_id, None)[0] 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) mi, opf_file = create_opf_file(self.db, book_id)
in_file = PersistentTemporaryFile('.'+input_format) in_file = PersistentTemporaryFile('.'+input_format)
with in_file: 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) index_is_id=True)
out_file = PersistentTemporaryFile('.' + self.output_format) out_file = PersistentTemporaryFile('.' + self.output_format)
@ -192,7 +199,10 @@ class QueueBulk(QProgressDialog):
args = [in_file.name, out_file.name, lrecs] args = [in_file.name, out_file.name, lrecs]
temp_files.append(out_file) 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.changed = True
self.setValue(self.i) self.setValue(self.i)

View File

@ -661,6 +661,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
def save_current_position(self): def save_current_position(self):
if not self.get_remember_current_page_opt(): if not self.get_remember_current_page_opt():
return return
if hasattr(self, 'current_index'):
try: try:
pos = self.view.bookmark() pos = self.view.bookmark()
bookmark = '%d#%s'%(self.current_index, pos) bookmark = '%d#%s'%(self.current_index, pos)

View File

@ -1312,6 +1312,23 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
self.notify('metadata', [id]) self.notify('metadata', [id])
return True 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): def delete_book(self, id, notify=True, commit=True, permanent=False):
''' '''
Removes book from the result cache and the underlying database. Removes book from the result cache and the underlying database.