mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
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:
parent
383f2c62e2
commit
2dd5346104
@ -476,3 +476,9 @@ save_original_format = True
|
|||||||
# how many should be shown, here.
|
# how many should be shown, here.
|
||||||
gui_view_history_size = 15
|
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'
|
||||||
|
|
||||||
|
@ -839,7 +839,7 @@ class ActionCopyToLibrary(InterfaceActionBase):
|
|||||||
class ActionTweakEpub(InterfaceActionBase):
|
class ActionTweakEpub(InterfaceActionBase):
|
||||||
name = 'Tweak ePub'
|
name = 'Tweak ePub'
|
||||||
actual_plugin = 'calibre.gui2.actions.tweak_epub:TweakEpubAction'
|
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):
|
class ActionNextMatch(InterfaceActionBase):
|
||||||
name = 'Next Match'
|
name = 'Next Match'
|
||||||
|
@ -10,12 +10,13 @@ import os
|
|||||||
from calibre.gui2 import error_dialog
|
from calibre.gui2 import error_dialog
|
||||||
from calibre.gui2.actions import InterfaceAction
|
from calibre.gui2.actions import InterfaceAction
|
||||||
from calibre.gui2.dialogs.tweak_epub import TweakEpub
|
from calibre.gui2.dialogs.tweak_epub import TweakEpub
|
||||||
|
from calibre.utils.config import tweaks
|
||||||
|
|
||||||
class TweakEpubAction(InterfaceAction):
|
class TweakEpubAction(InterfaceAction):
|
||||||
|
|
||||||
name = 'Tweak ePub'
|
name = 'Tweak ePub'
|
||||||
action_spec = (_('Tweak ePub'), 'trim.png',
|
action_spec = (_('Tweak Book'), 'trim.png',
|
||||||
_('Make small changes to ePub format books'),
|
_('Make small changes to ePub or HTMLZ format books'),
|
||||||
_('T'))
|
_('T'))
|
||||||
dont_add_to = frozenset(['context-menu-device'])
|
dont_add_to = frozenset(['context-menu-device'])
|
||||||
action_type = 'current'
|
action_type = 'current'
|
||||||
@ -26,33 +27,48 @@ class TweakEpubAction(InterfaceAction):
|
|||||||
def edit_epub_in_situ(self, *args):
|
def edit_epub_in_situ(self, *args):
|
||||||
row = self.gui.library_view.currentIndex()
|
row = self.gui.library_view.currentIndex()
|
||||||
if not row.isValid():
|
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)
|
_('No book selected'), show=True)
|
||||||
|
|
||||||
# Confirm 'EPUB' in formats
|
|
||||||
book_id = self.gui.library_view.model().id(row)
|
book_id = self.gui.library_view.model().id(row)
|
||||||
|
|
||||||
|
# Confirm 'EPUB' in formats
|
||||||
try:
|
try:
|
||||||
path_to_epub = self.gui.library_view.model().db.format(
|
path_to_epub = self.gui.library_view.model().db.format(
|
||||||
book_id, 'EPUB', index_is_id=True, as_path=True)
|
book_id, 'EPUB', index_is_id=True, as_path=True)
|
||||||
except:
|
except:
|
||||||
path_to_epub = None
|
path_to_epub = None
|
||||||
|
|
||||||
if not path_to_epub:
|
# Confirm 'HTMLZ' in formats
|
||||||
return error_dialog(self.gui, _('Cannot tweak ePub'),
|
try:
|
||||||
_('No ePub available. First convert the book to ePub.'),
|
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)
|
show=True)
|
||||||
|
|
||||||
# Launch modal dialog waiting for user to tweak or cancel
|
# 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:
|
if dlg.exec_() == dlg.Accepted:
|
||||||
self.update_db(book_id, dlg._output)
|
self.update_db(book_id, dlg._output)
|
||||||
dlg.cleanup()
|
dlg.cleanup()
|
||||||
os.remove(path_to_epub)
|
os.remove(path_to_book)
|
||||||
|
|
||||||
def update_db(self, book_id, rebuilt):
|
def update_db(self, book_id, rebuilt):
|
||||||
'''
|
'''
|
||||||
Update the calibre db with the tweaked epub
|
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)
|
open(rebuilt, 'rb'), index_is_id=True)
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os, shutil
|
import os, shutil
|
||||||
|
from itertools import repeat, izip
|
||||||
from calibre.utils.zipfile import ZipFile, ZIP_DEFLATED, ZIP_STORED
|
from calibre.utils.zipfile import ZipFile, ZIP_DEFLATED, ZIP_STORED
|
||||||
|
|
||||||
from PyQt4.Qt import QDialog
|
from PyQt4.Qt import QDialog
|
||||||
@ -30,9 +31,20 @@ class TweakEpub(QDialog, Ui_Dialog):
|
|||||||
self._epub = epub
|
self._epub = epub
|
||||||
self._exploded = None
|
self._exploded = None
|
||||||
self._output = 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
|
# Run the dialog setup generated from tweak_epub.ui
|
||||||
self.setupUi(self)
|
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.cancel_button.clicked.connect(self.reject)
|
||||||
self.explode_button.clicked.connect(self.explode)
|
self.explode_button.clicked.connect(self.explode)
|
||||||
@ -83,9 +95,11 @@ class TweakEpub(QDialog, Ui_Dialog):
|
|||||||
def do_rebuild(self, src):
|
def do_rebuild(self, src):
|
||||||
with ZipFile(src, 'w', compression=ZIP_DEFLATED) as zf:
|
with ZipFile(src, 'w', compression=ZIP_DEFLATED) as zf:
|
||||||
# Write mimetype
|
# 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
|
# 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 root, dirs, files in os.walk(self._exploded):
|
||||||
for fn in files:
|
for fn in files:
|
||||||
if fn in exclude_files:
|
if fn in exclude_files:
|
||||||
@ -97,11 +111,11 @@ class TweakEpub(QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
def preview(self):
|
def preview(self):
|
||||||
if not self._exploded:
|
if not self._exploded:
|
||||||
return error_dialog(self, _('Cannot preview'),
|
msg = _('You must first explode the %s before previewing.')
|
||||||
_('You must first explode the epub before previewing.'),
|
msg = msg%('HTMLZ' if self.ishtmlz else 'ePub')
|
||||||
show=True)
|
return error_dialog(self, _('Cannot preview'), msg, show=True)
|
||||||
|
|
||||||
tf = PersistentTemporaryFile('.epub')
|
tf = PersistentTemporaryFile('.htmlz' if self.ishtmlz else '.epub')
|
||||||
tf.close()
|
tf.close()
|
||||||
self._preview_files.append(tf.name)
|
self._preview_files.append(tf.name)
|
||||||
|
|
||||||
@ -110,7 +124,7 @@ class TweakEpub(QDialog, Ui_Dialog):
|
|||||||
self.gui.iactions['View']._view_file(tf.name)
|
self.gui.iactions['View']._view_file(tf.name)
|
||||||
|
|
||||||
def rebuild(self, *args):
|
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)
|
self.do_rebuild(self._output)
|
||||||
return QDialog.accept(self)
|
return QDialog.accept(self)
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Tweak ePub</string>
|
<string>Tweak {0}</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeGripEnabled">
|
<property name="sizeGripEnabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@ -26,7 +26,7 @@
|
|||||||
<item row="0" column="0" colspan="2">
|
<item row="0" column="0" colspan="2">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string><p>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 <b>and the editor windows you used to edit files in the epub</b>.</p><p>Rebuild the ePub, updating your calibre library.</p></string>
|
<string><p>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 <b>and the editor windows you used to edit files in the ePub</b>.</p><p>Rebuild the ePub, updating your calibre library.</p></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="wordWrap">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -35,11 +35,14 @@
|
|||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QPushButton" name="explode_button">
|
<widget class="QPushButton" name="explode_button">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Display contents of exploded {0}</string>
|
||||||
|
</property>
|
||||||
<property name="statusTip">
|
<property name="statusTip">
|
||||||
<string>Display contents of exploded ePub</string>
|
<string>Display contents of exploded {0}</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Explode ePub</string>
|
<string>&Explode {0}</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../../../resources/images.qrc">
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
@ -49,6 +52,9 @@
|
|||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QPushButton" name="cancel_button">
|
<widget class="QPushButton" name="cancel_button">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Discard changes</string>
|
||||||
|
</property>
|
||||||
<property name="statusTip">
|
<property name="statusTip">
|
||||||
<string>Discard changes</string>
|
<string>Discard changes</string>
|
||||||
</property>
|
</property>
|
||||||
@ -66,11 +72,14 @@
|
|||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Rebuild {0} from exploded contents</string>
|
||||||
|
</property>
|
||||||
<property name="statusTip">
|
<property name="statusTip">
|
||||||
<string>Rebuild ePub from exploded contents</string>
|
<string>Rebuild {0} from exploded contents</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Rebuild ePub</string>
|
<string>&Rebuild {0}</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../../../resources/images.qrc">
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
@ -81,7 +90,7 @@
|
|||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QPushButton" name="preview_button">
|
<widget class="QPushButton" name="preview_button">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Preview ePub</string>
|
<string>&Preview {0}</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../../../resources/images.qrc">
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
|
@ -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
|
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
|
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
|
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):
|
Example image tag (place the image within an 'Images' folder inside the epub after conversion):
|
||||||
<img style="width:10%" src="../Images/scenebreak.png" />
|
<img style="width:10%" src="../Images/scenebreak.png" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user