10000: report tables are always written LTR even for RTL locales
This commit is contained in:
parent
db8b95cf2d
commit
55fa920628
@ -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
|
||||
|
@ -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')
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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')
|
||||
|
@ -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]
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user