MOBI Output:Add --ignore-tables option. ALso fix nasty bug in GUI that was causing the MOBI specific conversion options to not have any effect.

This commit is contained in:
Kovid Goyal 2009-01-26 23:02:19 -08:00
commit 1fb46bc6a4
6 changed files with 69 additions and 40 deletions

View File

@ -79,6 +79,9 @@ class FormatState(object):
class MobiMLizer(object): class MobiMLizer(object):
def __init__(self, ignore_tables=False):
self.ignore_tables = ignore_tables
def transform(self, oeb, context): def transform(self, oeb, context):
oeb.logger.info('Converting XHTML to Mobipocket markup...') oeb.logger.info('Converting XHTML to Mobipocket markup...')
self.oeb = oeb self.oeb = oeb
@ -341,6 +344,8 @@ class MobiMLizer(object):
tag = 'tr' tag = 'tr'
elif display == 'table-cell': elif display == 'table-cell':
tag = 'td' tag = 'td'
if tag in TABLE_TAGS and self.ignore_tables:
tag = 'span' if tag == 'td' else 'div'
if tag in TABLE_TAGS: if tag in TABLE_TAGS:
for attr in ('rowspan', 'colspan'): for attr in ('rowspan', 'colspan'):
if attr in elem.attrib: if attr in elem.attrib:

View File

@ -524,6 +524,10 @@ def config(defaults=None):
help=_('Modify images to meet Palm device size limitations.')) help=_('Modify images to meet Palm device size limitations.'))
mobi('toc_title', ['--toc-title'], default=None, mobi('toc_title', ['--toc-title'], default=None,
help=_('Title for any generated in-line table of contents.')) help=_('Title for any generated in-line table of contents.'))
mobi('ignore_tables', ['--ignore-tables'], default=False,
help=_('Render HTML tables as blocks of text instead of actual '
'tables. This is neccessary if the HTML contains very large '
'or complex tables.'))
profiles = c.add_group('profiles', _('Device renderer profiles. ' profiles = c.add_group('profiles', _('Device renderer profiles. '
'Affects conversion of font sizes, image rescaling and rasterization ' 'Affects conversion of font sizes, image rescaling and rasterization '
'of tables. Valid profiles are: %s.') % ', '.join(_profiles)) 'of tables. Valid profiles are: %s.') % ', '.join(_profiles))
@ -581,7 +585,7 @@ def oeb2mobi(opts, inpath):
rasterizer.transform(oeb, context) rasterizer.transform(oeb, context)
trimmer = ManifestTrimmer() trimmer = ManifestTrimmer()
trimmer.transform(oeb, context) trimmer.transform(oeb, context)
mobimlizer = MobiMLizer() mobimlizer = MobiMLizer(ignore_tables=opts.ignore_tables)
mobimlizer.transform(oeb, context) mobimlizer.transform(oeb, context)
writer = MobiWriter(compression=compression, imagemax=imagemax) writer = MobiWriter(compression=compression, imagemax=imagemax)
writer.dump(oeb, outpath) writer.dump(oeb, outpath)

View File

@ -1039,9 +1039,19 @@ class OEBBook(object):
def _ensure_cover_image(self): def _ensure_cover_image(self):
cover = None cover = None
spine0 = self.spine[0] hcover = self.spine[0]
html = spine0.data if 'cover' in self.guide:
if self.metadata.cover: href = self.guide['cover'].href
item = self.manifest.hrefs[href]
media_type = item.media_type
if media_type in OEB_RASTER_IMAGES:
cover = item
elif media_type in OEB_DOCS:
hcover = item
html = hcover.data
if cover is not None:
pass
elif self.metadata.cover:
id = str(self.metadata.cover[0]) id = str(self.metadata.cover[0])
cover = self.manifest.ids[id] cover = self.manifest.ids[id]
elif MS_COVER_TYPE in self.guide: elif MS_COVER_TYPE in self.guide:
@ -1049,16 +1059,16 @@ class OEBBook(object):
cover = self.manifest.hrefs[href] cover = self.manifest.hrefs[href]
elif xpath(html, '//h:img[position()=1]'): elif xpath(html, '//h:img[position()=1]'):
img = xpath(html, '//h:img[position()=1]')[0] img = xpath(html, '//h:img[position()=1]')[0]
href = spine0.abshref(img.get('src')) href = hcover.abshref(img.get('src'))
cover = self.manifest.hrefs[href] cover = self.manifest.hrefs[href]
elif xpath(html, '//h:object[position()=1]'): elif xpath(html, '//h:object[position()=1]'):
object = xpath(html, '//h:object[position()=1]')[0] object = xpath(html, '//h:object[position()=1]')[0]
href = spine0.abshref(object.get('data')) href = hcover.abshref(object.get('data'))
cover = self.manifest.hrefs[href] cover = self.manifest.hrefs[href]
elif xpath(html, '//svg:svg[position()=1]'): elif xpath(html, '//svg:svg[position()=1]'):
svg = copy.deepcopy(xpath(html, '//svg:svg[position()=1]')[0]) svg = copy.deepcopy(xpath(html, '//svg:svg[position()=1]')[0])
href = os.path.splitext(spine0.href)[0] + '.svg' href = os.path.splitext(hcover.href)[0] + '.svg'
id, href = self.manifest.generate(spine0.id, href) id, href = self.manifest.generate(hcover.id, href)
cover = self.manifest.add(id, href, SVG_MIME, data=svg) cover = self.manifest.add(id, href, SVG_MIME, data=svg)
if cover and not self.metadata.cover: if cover and not self.metadata.cover:
self.metadata.add('cover', cover.id) self.metadata.add('cover', cover.id)

View File

@ -61,6 +61,7 @@ class Config(ResizableDialog, Ui_Dialog):
self.opt_toc_title.setVisible(False) self.opt_toc_title.setVisible(False)
self.toc_title_label.setVisible(False) self.toc_title_label.setVisible(False)
self.opt_rescale_images.setVisible(False) self.opt_rescale_images.setVisible(False)
self.opt_ignore_tables.setVisible(False)
def initialize(self): def initialize(self):
self.__w = [] self.__w = []

View File

@ -93,7 +93,7 @@
<item> <item>
<widget class="QStackedWidget" name="stack" > <widget class="QStackedWidget" name="stack" >
<property name="currentIndex" > <property name="currentIndex" >
<number>0</number> <number>1</number>
</property> </property>
<widget class="QWidget" name="metadata_page" > <widget class="QWidget" name="metadata_page" >
<layout class="QGridLayout" name="gridLayout_4" > <layout class="QGridLayout" name="gridLayout_4" >
@ -105,6 +105,36 @@
<string>Book Cover</string> <string>Book Cover</string>
</property> </property>
<layout class="QGridLayout" name="_2" > <layout class="QGridLayout" name="_2" >
<item row="0" column="0" >
<layout class="QHBoxLayout" name="_3" >
<item>
<widget class="ImageView" name="cover" >
<property name="text" >
<string/>
</property>
<property name="pixmap" >
<pixmap resource="../images.qrc" >:/images/book.svg</pixmap>
</property>
<property name="scaledContents" >
<bool>true</bool>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0" >
<widget class="QCheckBox" name="opt_prefer_metadata_cover" >
<property name="text" >
<string>Use cover from &amp;source file</string>
</property>
<property name="checked" >
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" > <item row="1" column="0" >
<layout class="QVBoxLayout" name="_4" > <layout class="QVBoxLayout" name="_4" >
<property name="spacing" > <property name="spacing" >
@ -156,36 +186,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="2" column="0" >
<widget class="QCheckBox" name="opt_prefer_metadata_cover" >
<property name="text" >
<string>Use cover from &amp;source file</string>
</property>
<property name="checked" >
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0" >
<layout class="QHBoxLayout" name="_3" >
<item>
<widget class="ImageView" name="cover" >
<property name="text" >
<string/>
</property>
<property name="pixmap" >
<pixmap resource="../images.qrc" >:/images/book.svg</pixmap>
</property>
<property name="scaledContents" >
<bool>true</bool>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
<zorder>opt_prefer_metadata_cover</zorder> <zorder>opt_prefer_metadata_cover</zorder>
<zorder></zorder> <zorder></zorder>
@ -479,6 +479,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0" >
<widget class="QCheckBox" name="opt_ignore_tables" >
<property name="text" >
<string>&amp;Ignore tables</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>

View File

@ -97,7 +97,7 @@ class OptionParser(_OptionParser):
def merge(self, parser): def merge(self, parser):
''' '''
Add options from parser to self. In case of conflicts, confilicting options from Add options from parser to self. In case of conflicts, conflicting options from
parser are skipped. parser are skipped.
''' '''
opts = list(parser.option_list) opts = list(parser.option_list)
@ -224,6 +224,8 @@ class OptionSet(object):
def update(self, other): def update(self, other):
for name in other.groups.keys(): for name in other.groups.keys():
self.groups[name] = other.groups[name] self.groups[name] = other.groups[name]
if name not in self.group_list:
self.group_list.append(name)
for pref in other.preferences: for pref in other.preferences:
if pref in self.preferences: if pref in self.preferences:
self.preferences.remove(pref) self.preferences.remove(pref)