Add an option in the bulk metadata edit dialog to restore the pre-conversion files for many books with a single click. Fixes #886116 ([Enhancement] Format Conversion Error)

This commit is contained in:
Kovid Goyal 2011-11-17 11:49:20 +05:30
parent a5fa43ad5b
commit 6d17b9323c
2 changed files with 101 additions and 50 deletions

View File

@ -23,6 +23,8 @@ from calibre.utils.icu import sort_key, capitalize
from calibre.utils.config import prefs, tweaks
from calibre.utils.magick.draw import identify_data
from calibre.utils.date import qt_to_dt
from calibre.ptempfile import SpooledTemporaryFile
from calibre.db import SPOOL_SIZE
def get_cover_data(stream, ext): # {{{
from calibre.ebooks.metadata.meta import get_metadata
@ -134,11 +136,12 @@ class MyBlockingBusy(QDialog): # {{{
do_autonumber, do_remove_format, remove_format, do_swap_ta, \
do_remove_conv, do_auto_author, series, do_series_restart, \
series_start_value, do_title_case, cover_action, clear_series, \
pubdate, adddate, do_title_sort, languages, clear_languages = self.args
pubdate, adddate, do_title_sort, languages, clear_languages, \
restore_original = self.args
# first loop: do author and title. These will commit at the end of each
# operation, because each operation modifies the file system. We want to
# first loop: All changes that modify the filesystem and commit
# immediately. We want to
# try hard to keep the DB and the file system in sync, even in the face
# of exceptions or forced exits.
if self.current_phase == 1:
@ -196,6 +199,27 @@ class MyBlockingBusy(QDialog): # {{{
if covers:
self.db.set_cover(id, covers[-1][0])
covers = []
if do_remove_format:
self.db.remove_format(id, remove_format, index_is_id=True,
notify=False, commit=True)
if restore_original:
formats = self.db.formats(id, index_is_id=True)
formats = formats.split(',') if formats else []
originals = [x.upper() for x in formats if
x.upper().startswith('ORIGINAL_')]
for ofmt in originals:
fmt = ofmt.replace('ORIGINAL_', '')
with SpooledTemporaryFile(SPOOL_SIZE) as stream:
self.db.copy_format_to(id, ofmt, stream,
index_is_id=True)
stream.seek(0)
self.db.add_format(id, fmt, stream, index_is_id=True,
notify=False)
self.db.remove_format(id, ofmt, index_is_id=True,
notify=False, commit=True)
elif self.current_phase == 2:
# All of these just affect the DB, so we can tolerate a total rollback
if do_auto_author:
@ -233,9 +257,6 @@ class MyBlockingBusy(QDialog): # {{{
num = next if do_autonumber and series else 1.0
self.db.set_series_index(id, num, notify=False, commit=False)
if do_remove_format:
self.db.remove_format(id, remove_format, index_is_id=True, notify=False, commit=False)
if do_remove_conv:
self.db.delete_conversion_options(id, 'PIPE', commit=False)
@ -936,6 +957,7 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
do_title_case = self.change_title_to_title_case.isChecked()
do_title_sort = self.update_title_sort.isChecked()
clear_languages = self.clear_languages.isChecked()
restore_original = self.restore_original.isChecked()
languages = self.languages.lang_codes
pubdate = adddate = None
if self.apply_pubdate.isChecked():
@ -955,7 +977,8 @@ class MetadataBulkDialog(ResizableDialog, Ui_MetadataBulkDialog):
do_autonumber, do_remove_format, remove_format, do_swap_ta,
do_remove_conv, do_auto_author, series, do_series_restart,
series_start_value, do_title_case, cover_action, clear_series,
pubdate, adddate, do_title_sort, languages, clear_languages)
pubdate, adddate, do_title_sort, languages, clear_languages,
restore_original)
bb = MyBlockingBusy(_('Applying changes to %d books.\nPhase {0} {1}%%.')
%len(self.ids), args, self.db, self.ids,

View File

@ -14,7 +14,7 @@
<string>Edit Meta information</string>
</property>
<property name="windowIcon">
<iconset resource="../../../work/calibre/resources/images.qrc">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/edit_input.png</normaloff>:/images/edit_input.png</iconset>
</property>
<layout class="QGridLayout" name="gridLayout_2">
@ -210,7 +210,7 @@
<string>Open Tag Editor</string>
</property>
<property name="icon">
<iconset resource="../../../work/calibre/resources/images.qrc">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/chapters.png</normaloff>:/images/chapters.png</iconset>
</property>
</widget>
@ -381,7 +381,7 @@ from the value in the box</string>
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../work/calibre/resources/images.qrc">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/trash.png</normaloff>:/images/trash.png</iconset>
</property>
</widget>
@ -429,7 +429,7 @@ from the value in the box</string>
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../work/calibre/resources/images.qrc">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/trash.png</normaloff>:/images/trash.png</iconset>
</property>
</widget>
@ -443,7 +443,30 @@ from the value in the box</string>
</property>
</widget>
</item>
<item row="13" column="0">
<item row="11" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>&amp;Languages:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>languages</cstring>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="LanguagesEdit" name="languages"/>
</item>
<item row="11" column="2">
<widget class="QCheckBox" name="clear_languages">
<property name="text">
<string>Remove &amp;all</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Remove &amp;format:</string>
@ -453,17 +476,44 @@ from the value in the box</string>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QComboBox" name="remove_format">
<property name="maximumSize">
<size>
<width>120</width>
<height>16777215</height>
</size>
</property>
</widget>
<item row="12" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QComboBox" name="remove_format">
<property name="maximumSize">
<size>
<width>120</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="restore_original">
<property name="toolTip">
<string>When doing a same format to same format conversion, for e.g., EPUB to EPUB, calibre saves the original EPUB as ORIGINAL_EPUB. This option tells calibre to restore the EPUB from ORIGINAL_EPUB. Useful if you did a bulk conversion of a large number of books and something went wrong.</string>
</property>
<property name="text">
<string>Restore pre conversion &amp;originals, if available</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="14" column="0">
<item row="13" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -479,7 +529,7 @@ from the value in the box</string>
</property>
</spacer>
</item>
<item row="15" column="0" colspan="3">
<item row="14" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="change_title_to_title_case">
@ -529,7 +579,7 @@ Future conversion of these books will use the default settings.</string>
</item>
</layout>
</item>
<item row="16" column="0" colspan="3">
<item row="15" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Change &amp;cover</string>
@ -559,7 +609,7 @@ Future conversion of these books will use the default settings.</string>
</layout>
</widget>
</item>
<item row="17" column="0">
<item row="16" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -572,29 +622,6 @@ Future conversion of these books will use the default settings.</string>
</property>
</spacer>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>&amp;Languages:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>languages</cstring>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="LanguagesEdit" name="languages"/>
</item>
<item row="11" column="2">
<widget class="QCheckBox" name="clear_languages">
<property name="text">
<string>Remove &amp;all</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
@ -1199,13 +1226,13 @@ not multiple and the destination field is multiple</string>
<tabstop>languages</tabstop>
<tabstop>clear_languages</tabstop>
<tabstop>remove_format</tabstop>
<tabstop>restore_original</tabstop>
<tabstop>change_title_to_title_case</tabstop>
<tabstop>update_title_sort</tabstop>
<tabstop>remove_conversion_settings</tabstop>
<tabstop>cover_generate</tabstop>
<tabstop>cover_remove</tabstop>
<tabstop>cover_from_fmt</tabstop>
<tabstop>starting_from</tabstop>
<tabstop>multiple_separator</tabstop>
<tabstop>test_text</tabstop>
<tabstop>test_result</tabstop>
@ -1229,9 +1256,10 @@ not multiple and the destination field is multiple</string>
<tabstop>destination_field</tabstop>
<tabstop>search_for</tabstop>
<tabstop>case_sensitive</tabstop>
<tabstop>starting_from</tabstop>
</tabstops>
<resources>
<include location="../../../work/calibre/resources/images.qrc"/>
<include location="../../../../resources/images.qrc"/>
</resources>
<connections>
<connection>