10000: report tables are always written LTR even for RTL locales

This commit is contained in:
Paul Franklin 2017-04-30 11:44:13 -07:00
parent db8b95cf2d
commit 55fa920628
9 changed files with 101 additions and 34 deletions

View File

@ -6,6 +6,7 @@
# Copyright (C) 2007 Brian G. Matherly
# Copyright (C) 2009 Benny Malengier
# Copyright (C) 2009 Gary Burton
# Copyright (C) 2017 Paul Franklin
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -78,6 +79,13 @@ class BaseDoc(metaclass=ABCMeta):
self._creator = ""
self.init_called = False
self.uistate = uistate
self._rtl_doc = False # does the document have right-to-left text?
def set_rtl_doc(self, value):
self._rtl_doc = value
def get_rtl_doc(self):
return self._rtl_doc
def init(self):
self.init_called = True

View File

@ -79,6 +79,7 @@ class Report:
self._get_date = locale.get_date
self._get_type = locale.get_type
self._ldd = locale.date_displayer
self.doc.set_rtl_doc(locale.rtl_locale)
self._name_display = NameDisplay(locale) # a legacy/historical name
self._name_display.set_name_format(self.database.name_formats)
fmt_default = config.get('preferences.name-format')

View File

@ -112,6 +112,9 @@ _LOCALE_NAMES = {
'zh_TW': ('Chinese_Taiwan', '950', _("Chinese (Traditional)")),
}
# locales with right-to-left text
_RTL_LOCALES = ('ar', 'he')
# locales with less than 70% currently translated
INCOMPLETE_TRANSLATIONS = ('ar', 'bg', 'he', 'ja', 'sq', 'ta', 'tr')
@ -526,6 +529,10 @@ class GrampsLocale:
self._win_bindtextdomain(self.localedomain.encode('utf-8'),
self.localedir.encode('utf-8'))
self.rtl_locale = False
if self.language[0] in _RTL_LOCALES:
self.rtl_locale = True # right-to-left
def _init_secondary_locale(self):
"""
Init a secondary locale. Secondary locales are used to provide
@ -560,6 +567,9 @@ class GrampsLocale:
self.numeric = self.currency = self.calendar = self.collation = self.lang
self.rtl_locale = False
if self.language[0] in _RTL_LOCALES:
self.rtl_locale = True # right-to-left
def __init__(self, localedir=None, lang=None, domain=None, languages=None):
"""

View File

@ -6,7 +6,7 @@
# Copyright (C) 2009-2010 Benny Malengier <benny.malengier@gramps-project.org>
# Copyright (C) 2010 Peter Landgren
# Copyright (C) 2011 Adam Stein <adam@csh.rit.edu>
# Copyright (C) 2012 Paul Franklin
# Copyright (C) 2012,2017 Paul Franklin
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -153,6 +153,7 @@ class AsciiDoc(BaseDoc, TextDoc):
self.tbl_style = None
self.in_cell = None
self.ncols = 0
self.column_order = []
self.cellpars = []
self.cell_lines = []
self.cell_widths = []
@ -309,6 +310,11 @@ class AsciiDoc(BaseDoc, TextDoc):
styles = self.get_style_sheet()
self.tbl_style = styles.get_table_style(style_name)
self.ncols = self.tbl_style.get_columns()
self.column_order = []
for cell in range(self.ncols):
self.column_order.append(cell)
if self.get_rtl_doc():
self.column_order.reverse()
#--------------------------------------------------------------------
#
@ -333,7 +339,7 @@ class AsciiDoc(BaseDoc, TextDoc):
self.maxlines = 0
table_width = (self.get_usable_width() *
self.tbl_style.get_width() / 100.0)
for cell in range(self.ncols):
for cell in self.column_order:
self.cell_widths[cell] = int(
table_width * self.tbl_style.get_column_width(cell) / 100.0)
@ -346,7 +352,7 @@ class AsciiDoc(BaseDoc, TextDoc):
def end_row(self):
self.in_cell = 0
cell_text = [None]*self.ncols
for cell in range(self.ncols):
for cell in self.column_order:
if self.cell_widths[cell]:
blanks = ' '*self.cell_widths[cell] + '\n'
if self.cell_lines[cell] < self.maxlines:
@ -355,7 +361,7 @@ class AsciiDoc(BaseDoc, TextDoc):
)
cell_text[cell] = self.cellpars[cell].split('\n')
for line in range(self.maxlines):
for cell in range(self.ncols):
for cell in self.column_order:
if self.cell_widths[cell]:
self.file.write(cell_text[cell][line])
self.file.write('\n')

View File

@ -67,7 +67,7 @@ _CLICKABLE = '\\url{\\1}'
#
#------------------------------------------------------------------------
# For an interim mark e.g. for an intended linebreak I use a special pattern.
# It shouldn't interfere with normal text. In LaTeX charackter '&' is used
# It shouldn't interfere with normal text. In LaTeX character '&' is used
# for column separation in tables and may occur there in series. The pattern
# is used here before column separation is set. On the other hand incoming
# text can't show this pattern for it would have been replaced by '\&\&'.
@ -703,7 +703,6 @@ class LaTeXDoc(BaseDoc, TextDoc):
if self.in_multrow_cell: # cols of rows: convert to rows of cols
self.repack_row()
else:
self.tabmem = TabMem(text)
self.tabmem.rows.append(self.tabrow)
elif tab_state == TAB_BEG: # text: \\begin{longtable}[l]{
self._backend.write(''.join(('\\grinittab{\\textwidth}{',
@ -770,8 +769,6 @@ class LaTeXDoc(BaseDoc, TextDoc):
self.tabmem.rows[-1].addit = self.tabrow.addit
self.in_multrow_cell = False
return
def calc_latex_widths(self):
"""
@ -954,7 +951,7 @@ class LaTeXDoc(BaseDoc, TextDoc):
self._backend.open()
# Font size control seems to be limited. For now, ignore
# any style constraints, and use 12pt has the default
# any style constraints, and use 12pt as the default
options = "12pt"
@ -1026,7 +1023,6 @@ class LaTeXDoc(BaseDoc, TextDoc):
thisstyle.first_line_indent = first
self.latexstyle[style_name] = thisstyle
def close(self):
"""Clean up and close the document"""
if self.in_list:
@ -1132,6 +1128,11 @@ class LaTeXDoc(BaseDoc, TextDoc):
styles = self.get_style_sheet()
self.tblstyle = styles.get_table_style(style_name)
self.numcols = self.tblstyle.get_columns()
self.column_order = []
for cell in range(self.numcols):
self.column_order.append(cell)
if self.get_rtl_doc():
self.column_order.reverse()
tblfmt = '*{%d}{l}' % self.numcols
self.emit('\\begin{longtable}[l]{%s}\n' % (tblfmt), TAB_BEG)
@ -1148,7 +1149,7 @@ class LaTeXDoc(BaseDoc, TextDoc):
self.doline = False
self.skipfirst = False
self.curcol = 0
self.currow = self.currow + 1
self.currow += 1
def end_row(self):
"""End the row (new line)"""
@ -1168,7 +1169,7 @@ class LaTeXDoc(BaseDoc, TextDoc):
We always place our data inside braces
for safety of formatting."""
self.colspan = span
self.curcol = self.curcol + self.colspan
self.curcol += self.colspan
styles = self.get_style_sheet()
self.cstyle = styles.get_cell_style(style_name)
@ -1208,12 +1209,10 @@ class LaTeXDoc(BaseDoc, TextDoc):
self.emit('\\multicolumn{%d}{%s}' % (span, cellfmt), CELL_BEG, span)
def end_cell(self):
"""Prepares for next cell"""
self.emit('', CELL_END)
def add_media(self, infile, pos, x, y, alt='', style_name=None, crop=None):
"""Add photo to report"""
outfile = os.path.splitext(infile)[0]

View File

@ -7,7 +7,7 @@
# Copyright (C) 2010 Peter Landgren
# Copyright (C) 2010 Jakim Friant
# Copyright (C) 2011 Adam Stein <adam@csh.rit.edu>
# Copyright (C) 2012 Paul Franklin
# Copyright (C) 2012,2017 Paul Franklin
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -424,6 +424,8 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
self.filename = None
self.lang = None
self._backend = None
self.column_order = None
self.row_cells = None
self.span = 0
self.level = 0
self.time = "0000-00-00T00:00:00"
@ -1046,7 +1048,12 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
styles = self.get_style_sheet()
table = styles.get_table_style(style_name)
for col in range(table.get_columns()):
self.column_order = []
for cell in range(table.get_columns()):
self.column_order.append(cell)
if self.get_rtl_doc():
self.column_order.reverse()
for col in self.column_order:
self.cntnt.write(
'<table:table-column table:style-name="%s.%s"/>\n'
% (style_name, str(chr(ord('A')+col)))
@ -1063,17 +1070,25 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
open a row
"""
self.cntnt.write('<table:table-row>\n')
self.row_cells = []
self.cntnt_saved = self.cntnt # save the content up to now
def end_row(self):
"""
close a row
"""
self.cntnt = self.cntnt_saved # restore the original contents
if self.get_rtl_doc():
self.row_cells.reverse()
for cell in self.row_cells:
self.cntnt.write(cell)
self.cntnt.write('</table:table-row>\n')
def start_cell(self, style_name, span=1):
"""
open a cell
"""
self.cntnt = StringIO() # start a new buffer (with the expected name)
self.span = span
self.cntnt.write(
'<table:table-cell table:style-name="%s" ' % style_name +
@ -1093,6 +1108,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
#for col in range(1, self.span):
# self.cntnt.write('<table:covered-table-cell/>\n')
self.new_cell = 0
self.row_cells.append(self.cntnt.getvalue()) # save the cell, for now
def start_bold(self):
"""

View File

@ -6,6 +6,7 @@
# Copyright (C) 2009 Gary Burton
# Copyright (C) 2010 Peter Landgren
# Copyright (C) 2011 Adam Stein <adam@csh.rit.edu>
# Copyright (C) 2017 Paul Franklin
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -133,6 +134,7 @@ class RTFDoc(BaseDoc, TextDoc):
)
self.in_table = 0
self.text = ""
self.p_wide = float(self.paper.get_usable_width())
#--------------------------------------------------------------------
#
@ -153,7 +155,7 @@ class RTFDoc(BaseDoc, TextDoc):
#--------------------------------------------------------------------
#
# Starts a paragraph. Instead of using a style sheet, generate the
# Starts a paragraph. Instead of using a style sheet, generate
# the style for each paragraph on the fly. Not the ideal, but it
# does work.
#
@ -313,7 +315,20 @@ class RTFDoc(BaseDoc, TextDoc):
def start_table(self, name, style_name):
self.in_table = 1
styles = self.get_style_sheet()
self.tbl_style = styles.get_table_style(style_name)
table_style = styles.get_table_style(style_name)
self._cells = []
if self.get_rtl_doc():
cell_percent = 100.0
else:
cell_percent = 0.0
for cell in range(table_style.get_columns()):
if self.get_rtl_doc():
cell_percent -= float(table_style.get_column_width(cell))
else:
cell_percent += float(table_style.get_column_width(cell))
self._cells.append(twips((self.p_wide * cell_percent) / 100.0))
if self._cells[-1:] == [0]:
self._cells[-1:] = [twips(self.p_wide)] # left edge => right edge
#--------------------------------------------------------------------
#
@ -328,24 +343,32 @@ class RTFDoc(BaseDoc, TextDoc):
# Start a row. RTF uses the \trowd to start a row. RTF also specifies
# all the cell data after it has specified the cell definitions for
# the row. Therefore it is necessary to keep a list of cell contents
# that is to be written after all the cells are defined.
# that is to be written after all the cells are defined. It is also
# necessary to keep a list of the row columns definitions, since for
# RTL columns the columns which are processed last (in LTR) come first,
# and we don't know which will be skipped with a non-one "span" argument
# until we process them
#
#--------------------------------------------------------------------
def start_row(self):
self.contents = []
self.columns = []
self.cell = 0
self.prev = 0
self.cell_percent = 0.0
self.text = ""
self.file.write('\\trowd\n')
#--------------------------------------------------------------------
#
# End a row. Write the cell contents, separated by the \cell marker,
# then terminate the row
# then terminate the row with a \row marker
#
#--------------------------------------------------------------------
def end_row(self):
for column in sorted(self.columns):
for line in column[1]:
self.file.write(line)
if self.get_rtl_doc():
self.contents.reverse()
self.file.write('{')
for line in self.contents:
self.file.write(line)
@ -356,29 +379,26 @@ class RTFDoc(BaseDoc, TextDoc):
#
# Start a cell. Dump out the cell specifics, such as borders. Cell
# widths are kind of interesting. RTF doesn't specify how wide a cell
# is, but rather where it's right edge is in relationship to the
# is, but rather where its right edge is in relationship to the
# left margin. This means that each cell is the cumlative of the
# previous cells plus its own width.
#
#--------------------------------------------------------------------
def start_cell(self, style_name, span=1):
cell_data = []
styles = self.get_style_sheet()
s = styles.get_cell_style(style_name)
self.remain = span -1
if s.get_top_border():
self.file.write('\\clbrdrt\\brdrs\\brdrw10\n')
cell_data.append('\\clbrdrt\\brdrs\\brdrw10\n')
if s.get_bottom_border():
self.file.write('\\clbrdrb\\brdrs\\brdrw10\n')
cell_data.append('\\clbrdrb\\brdrs\\brdrw10\n')
if s.get_left_border():
self.file.write('\\clbrdrl\\brdrs\\brdrw10\n')
cell_data.append('\\clbrdrl\\brdrs\\brdrw10\n')
if s.get_right_border():
self.file.write('\\clbrdrr\\brdrs\\brdrw10\n')
table_width = float(self.paper.get_usable_width())
for cell in range(self.cell, self.cell+span):
self.cell_percent += float(self.tbl_style.get_column_width(cell))
cell_width = twips((table_width * self.cell_percent)/100.0)
cell_data.append('\\clbrdrr\\brdrs\\brdrw10\n')
self.need_nl = False
self.file.write('\\cellx%d\n' % cell_width)
cell_data.append('\\cellx%d\n' % self._cells[self.cell + span - 1])
self.columns.append([self._cells[self.cell + span - 1], cell_data])
self.cell += 1
#--------------------------------------------------------------------

View File

@ -7,7 +7,7 @@
# Copyright (C) 2009 Brian Matherly
# Copyright (C) 2010 Peter Landgren
# Copyright (C) 2010 Jakim Friant
# Copyright (C) 2011-2012 Paul Franklin
# Copyright (C) 2011-2017 Paul Franklin
# Copyright (C) 2012 Craig Anderson
#
# This program is free software; you can redistribute it and/or modify
@ -1450,6 +1450,8 @@ class CairoDoc(BaseDoc, TextDoc, DrawDoc):
# this is an ugly hack, but got no better idea.
self._active_row_style = list(map(style.get_column_width,
list(range(style.get_columns()))))
if self.get_rtl_doc():
self._active_row_style.reverse()
def end_table(self):
self._active_element = self._active_element.get_parent()
@ -1460,6 +1462,8 @@ class CairoDoc(BaseDoc, TextDoc, DrawDoc):
self._active_element = new_row
def end_row(self):
if self.get_rtl_doc():
self._active_element._children.reverse()
self._active_element = self._active_element.get_parent()
def start_cell(self, style_name, span=1):

View File

@ -919,12 +919,14 @@ class FamilyGroupOptions(MenuReportOptions):
cell.set_padding(0.1)
cell.set_bottom_border(1)
cell.set_left_border(1)
cell.set_right_border(1) # for RTL
default_style.add_cell_style('FGR-TextContents', cell)
cell = TableCellStyle()
cell.set_padding(0.1)
cell.set_bottom_border(0)
cell.set_left_border(1)
cell.set_right_border(1) # for RTL
cell.set_padding(0.1)
default_style.add_cell_style('FGR-TextChild1', cell)
@ -932,6 +934,7 @@ class FamilyGroupOptions(MenuReportOptions):
cell.set_padding(0.1)
cell.set_bottom_border(1)
cell.set_left_border(1)
cell.set_right_border(1) # for RTL
cell.set_padding(0.1)
default_style.add_cell_style('FGR-TextChild2', cell)