DOCX Output: Start work on table styling

This commit is contained in:
Kovid Goyal 2015-04-05 10:57:50 +05:30
parent 1b4e2a8858
commit cb69ee84ac

View File

@ -7,12 +7,38 @@ __license__ = 'GPL v3'
__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
from calibre.ebooks.docx.names import makeelement
from calibre.ebooks.docx.writer.utils import convert_color
def as_percent(x):
if x and x.endswith('%'):
try:
return float(x.rstrip('%'))
except Exception:
pass
def convert_width(tag_style):
if tag_style is not None:
w = tag_style._get('width')
wp = as_percent(w)
if w == 'auto':
return ('auto', 0)
elif wp is not None:
return ('pct', int(wp * 50))
else:
try:
return ('dxa', int(float(tag_style['width']) * 20))
except Exception:
pass
return ('auto', 0)
class Cell(object):
def __init__(self, html_tag, tag_style):
def __init__(self, row, html_tag, tag_style):
self.row = row
self.html_tag = html_tag
self.items = []
self.width = convert_width(tag_style)
self.background_color = None if tag_style is None else convert_color(tag_style.backgroundColor)
def add_block(self, block):
self.items.append(block)
@ -23,18 +49,28 @@ class Cell(object):
def serialize(self, parent):
tc = makeelement(parent, 'w:tc')
tcPr = makeelement(tc, 'w:tcPr')
makeelement(tcPr, 'w:tcW', w_type=self.width[0], w_w=str(self.width[1]))
# For some reason, Word 2007 refuses to honor <w:shd> at the table or row
# level, despite what the specs say, so we inherit and apply at the
# cell level
bc = self.background_color or self.row.background_color or self.row.table.background_color
if bc:
makeelement(tcPr, 'w:shd', w_val="clear", w_color="auto", w_fill=bc)
for item in self.items:
item.serialize(tc)
class Row(object):
def __init__(self, html_tag, tag_style=None):
def __init__(self, table, html_tag, tag_style=None):
self.table = table
self.html_tag = html_tag
self.cells = []
self.current_cell = None
self.background_color = None if tag_style is None else convert_color(tag_style.backgroundColor)
def start_new_cell(self, html_tag, tag_style):
self.current_cell = Cell(html_tag, tag_style)
self.current_cell = Cell(self, html_tag, tag_style)
def finish_tag(self, html_tag):
if self.current_cell is not None:
@ -50,6 +86,9 @@ class Row(object):
def serialize(self, parent):
tr = makeelement(parent, 'w:tr')
tblPrEx = makeelement(tr, 'w:tblPrEx')
if len(tblPrEx) == 0:
tr.remove(tblPrEx)
for cell in self.cells:
cell.serialize(tr)
@ -59,6 +98,13 @@ class Table(object):
self.html_tag = html_tag
self.rows = []
self.current_row = None
self.width = convert_width(tag_style)
self.background_color = None if tag_style is None else convert_color(tag_style.backgroundColor)
self.jc = None
if tag_style is not None:
ml, mr = tag_style._get('margin-left'), tag_style.get('margin-right')
if ml == 'auto':
self.jc = 'center' if mr == 'auto' else 'right'
def finish_tag(self, html_tag):
if self.current_row is not None:
@ -72,7 +118,7 @@ class Table(object):
def start_new_row(self, html_tag, html_style):
if self.current_row is not None:
self.rows.append(self.current_row)
self.current_row = Row(html_tag, html_style)
self.current_row = Row(self, html_tag, html_style)
def start_new_cell(self, html_tag, html_style):
if self.current_row is None:
@ -91,6 +137,8 @@ class Table(object):
return
tbl = makeelement(parent, 'w:tbl')
tblPr = makeelement(tbl, 'w:tblPr')
tblPr
makeelement(tblPr, 'w:tblW', w_type=self.width[0], w_w=str(self.width[1]))
if self.jc is not None:
makeelement(tblPr, 'w:jc', w_val=self.jc)
for row in rows:
row.serialize(tbl)