Tweak EPUB: Also allow tweaking of HTMLZ files (when both EPUB and HTMLZ are present, EPUB is preferred, can be changed via Preferences->Tweaks).

This commit is contained in:
Kovid Goyal 2012-01-07 23:17:12 +05:30
parent 383f2c62e2
commit 2dd5346104
6 changed files with 71 additions and 26 deletions

View File

@ -476,3 +476,9 @@ save_original_format = True
# how many should be shown, here.
gui_view_history_size = 15
#: When using the 'Tweak Book' action, which format to prefer
# When tweaking a book that has multiple formats, calibre picks one
# automatically. By default EPUB is preferred to HTMLZ. If you would like to
# prefer HTMLZ to EPUB for tweaking, change this to 'htmlz'
tweak_book_prefer = 'epub'

View File

@ -839,7 +839,7 @@ class ActionCopyToLibrary(InterfaceActionBase):
class ActionTweakEpub(InterfaceActionBase):
name = 'Tweak ePub'
actual_plugin = 'calibre.gui2.actions.tweak_epub:TweakEpubAction'
description = _('Make small tweaks to epub files in your calibre library')
description = _('Make small tweaks to epub or htmlz files in your calibre library')
class ActionNextMatch(InterfaceActionBase):
name = 'Next Match'

View File

@ -10,12 +10,13 @@ import os
from calibre.gui2 import error_dialog
from calibre.gui2.actions import InterfaceAction
from calibre.gui2.dialogs.tweak_epub import TweakEpub
from calibre.utils.config import tweaks
class TweakEpubAction(InterfaceAction):
name = 'Tweak ePub'
action_spec = (_('Tweak ePub'), 'trim.png',
_('Make small changes to ePub format books'),
action_spec = (_('Tweak Book'), 'trim.png',
_('Make small changes to ePub or HTMLZ format books'),
_('T'))
dont_add_to = frozenset(['context-menu-device'])
action_type = 'current'
@ -26,33 +27,48 @@ class TweakEpubAction(InterfaceAction):
def edit_epub_in_situ(self, *args):
row = self.gui.library_view.currentIndex()
if not row.isValid():
return error_dialog(self.gui, _('Cannot tweak ePub'),
return error_dialog(self.gui, _('Cannot tweak Book'),
_('No book selected'), show=True)
# Confirm 'EPUB' in formats
book_id = self.gui.library_view.model().id(row)
# Confirm 'EPUB' in formats
try:
path_to_epub = self.gui.library_view.model().db.format(
book_id, 'EPUB', index_is_id=True, as_path=True)
except:
path_to_epub = None
if not path_to_epub:
return error_dialog(self.gui, _('Cannot tweak ePub'),
_('No ePub available. First convert the book to ePub.'),
# Confirm 'HTMLZ' in formats
try:
path_to_htmlz = self.gui.library_view.model().db.format(
book_id, 'HTMLZ', index_is_id=True, as_path=True)
except:
path_to_htmlz = None
if not path_to_epub and not path_to_htmlz:
return error_dialog(self.gui, _('Cannot tweak Book'),
_('The book must be in ePub or HTMLZ format to tweak.'
'\n\nFirst convert the book to ePub or HTMLZ.'),
show=True)
# Launch modal dialog waiting for user to tweak or cancel
dlg = TweakEpub(self.gui, path_to_epub)
if tweaks['tweak_book_prefer'] == 'htmlz':
path_to_book = path_to_htmlz or path_to_epub
else:
path_to_book = path_to_epub or path_to_htmlz
dlg = TweakEpub(self.gui, path_to_book)
if dlg.exec_() == dlg.Accepted:
self.update_db(book_id, dlg._output)
dlg.cleanup()
os.remove(path_to_epub)
os.remove(path_to_book)
def update_db(self, book_id, rebuilt):
'''
Update the calibre db with the tweaked epub
'''
self.gui.library_view.model().db.add_format(book_id, 'EPUB',
fmt = os.path.splitext(rebuilt)[1][1:].upper()
self.gui.library_view.model().db.add_format(book_id, fmt,
open(rebuilt, 'rb'), index_is_id=True)

View File

@ -7,6 +7,7 @@ __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import os, shutil
from itertools import repeat, izip
from calibre.utils.zipfile import ZipFile, ZIP_DEFLATED, ZIP_STORED
from PyQt4.Qt import QDialog
@ -30,9 +31,20 @@ class TweakEpub(QDialog, Ui_Dialog):
self._epub = epub
self._exploded = None
self._output = None
self.ishtmlz = epub.lower().endswith('.htmlz')
self.rebuilt_name = 'rebuilt.' + ('htmlz' if self.ishtmlz else 'epub')
# Run the dialog setup generated from tweak_epub.ui
self.setupUi(self)
for x, props in [(self, ['windowTitle']), (self.label, ['text'])]+\
list(izip([self.cancel_button, self.explode_button,
self.rebuild_button, self.preview_button],
repeat(['text', 'statusTip', 'toolTip']))):
for prop in props:
val = unicode(getattr(x, prop)())
val = val.format('HTMLZ' if self.ishtmlz else 'ePub')
prop = 'set' + prop[0].upper() + prop[1:]
getattr(x, prop)(val)
self.cancel_button.clicked.connect(self.reject)
self.explode_button.clicked.connect(self.explode)
@ -83,9 +95,11 @@ class TweakEpub(QDialog, Ui_Dialog):
def do_rebuild(self, src):
with ZipFile(src, 'w', compression=ZIP_DEFLATED) as zf:
# Write mimetype
zf.write(os.path.join(self._exploded,'mimetype'), 'mimetype', compress_type=ZIP_STORED)
mt = os.path.join(self._exploded, 'mimetype')
if os.path.exists(mt):
zf.write(mt, 'mimetype', compress_type=ZIP_STORED)
# Write everything else
exclude_files = ['.DS_Store','mimetype','iTunesMetadata.plist','rebuilt.epub']
exclude_files = ['.DS_Store','mimetype','iTunesMetadata.plist',self.rebuilt_name]
for root, dirs, files in os.walk(self._exploded):
for fn in files:
if fn in exclude_files:
@ -97,11 +111,11 @@ class TweakEpub(QDialog, Ui_Dialog):
def preview(self):
if not self._exploded:
return error_dialog(self, _('Cannot preview'),
_('You must first explode the epub before previewing.'),
show=True)
msg = _('You must first explode the %s before previewing.')
msg = msg%('HTMLZ' if self.ishtmlz else 'ePub')
return error_dialog(self, _('Cannot preview'), msg, show=True)
tf = PersistentTemporaryFile('.epub')
tf = PersistentTemporaryFile('.htmlz' if self.ishtmlz else '.epub')
tf.close()
self._preview_files.append(tf.name)
@ -110,7 +124,7 @@ class TweakEpub(QDialog, Ui_Dialog):
self.gui.iactions['View']._view_file(tf.name)
def rebuild(self, *args):
self._output = os.path.join(self._exploded, 'rebuilt.epub')
self._output = os.path.join(self._exploded, self.rebuilt_name)
self.do_rebuild(self._output)
return QDialog.accept(self)

View File

@ -14,7 +14,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Tweak ePub</string>
<string>Tweak {0}</string>
</property>
<property name="sizeGripEnabled">
<bool>false</bool>
@ -26,7 +26,7 @@
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;p&gt;Explode the ePub to display contents in a file browser window. To tweak individual files, right-click, then 'Open with...' your editor of choice. When tweaks are complete, close the file browser window &lt;b&gt;and the editor windows you used to edit files in the epub&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;Rebuild the ePub, updating your calibre library.&lt;/p&gt;</string>
<string>&lt;p&gt;Explode the {0} to display contents in a file browser window. To tweak individual files, right-click, then 'Open with...' your editor of choice. When tweaks are complete, close the file browser window &lt;b&gt;and the editor windows you used to edit files in the ePub&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;Rebuild the ePub, updating your calibre library.&lt;/p&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@ -35,11 +35,14 @@
</item>
<item row="1" column="0">
<widget class="QPushButton" name="explode_button">
<property name="toolTip">
<string>Display contents of exploded {0}</string>
</property>
<property name="statusTip">
<string>Display contents of exploded ePub</string>
<string>Display contents of exploded {0}</string>
</property>
<property name="text">
<string>&amp;Explode ePub</string>
<string>&amp;Explode {0}</string>
</property>
<property name="icon">
<iconset resource="../../../../resources/images.qrc">
@ -49,6 +52,9 @@
</item>
<item row="3" column="0">
<widget class="QPushButton" name="cancel_button">
<property name="toolTip">
<string>Discard changes</string>
</property>
<property name="statusTip">
<string>Discard changes</string>
</property>
@ -66,11 +72,14 @@
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Rebuild {0} from exploded contents</string>
</property>
<property name="statusTip">
<string>Rebuild ePub from exploded contents</string>
<string>Rebuild {0} from exploded contents</string>
</property>
<property name="text">
<string>&amp;Rebuild ePub</string>
<string>&amp;Rebuild {0}</string>
</property>
<property name="icon">
<iconset resource="../../../../resources/images.qrc">
@ -81,7 +90,7 @@
<item row="1" column="1">
<widget class="QPushButton" name="preview_button">
<property name="text">
<string>&amp;Preview ePub</string>
<string>&amp;Preview {0}</string>
</property>
<property name="icon">
<iconset resource="../../../../resources/images.qrc">

View File

@ -323,7 +323,7 @@ remove all non-breaking-space entities, or may include false positive matches re
tags, i.e. horizontal rules, and <img> tags are exceptions. Horizontal rules can optionally be specified with styles, if you
choose to add your own style be sure to include the 'width' setting, otherwise the style information will be discarded. Image
tags can used, but |app| does not provide the ability to add the image during conversion, this must be done after the fact using
the 'Tweak Epub' feature, or Sigil.
the 'Tweak Book' feature, or Sigil.
Example image tag (place the image within an 'Images' folder inside the epub after conversion):
<img style="width:10%" src="../Images/scenebreak.png" />