517 lines
17 KiB
Python
517 lines
17 KiB
Python
#
|
|
# Gramps - a GTK+/GNOME based genealogy program
|
|
#
|
|
# Copyright (C) 2000-2004 Donald N. Allingham
|
|
#
|
|
# 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
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# Standard Python Modules
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
import os
|
|
import tempfile
|
|
import zipfile
|
|
from ...const import GRAMPS_LOCALE as glocale
|
|
_ = glocale.translation.gettext
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# Gramps modules
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
from .tabbeddoc import *
|
|
from ...const import PROGRAM_NAME, VERSION
|
|
from ...errors import ReportError
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# Constants
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
|
|
_XMLNS = '''\
|
|
xmlns:office="%(urn)soffice:1.0"
|
|
xmlns:style="%(urn)sstyle:1.0"
|
|
xmlns:text="%(urn)stext:1.0"
|
|
xmlns:table="%(urn)stable:1.0"
|
|
xmlns:draw="%(urn)sdrawing:1.0"
|
|
xmlns:fo="%(urn)sxsl-fo-compatible:1.0"
|
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
xmlns:meta="%(urn)smeta:1.0"
|
|
xmlns:number="%(urn)sdatastyle:1.0"
|
|
xmlns:svg="%(urn)ssvg-compatible:1.0"
|
|
xmlns:chart="%(urn)schart:1.0"
|
|
xmlns:dr3d="%(urn)sdr3d:1.0"
|
|
xmlns:math="http://www.w3.org/1998/Math/MathML"
|
|
xmlns:form="%(urn)sform:1.0"
|
|
xmlns:script="%(urn)sscript:1.0"
|
|
xmlns:dom="http://www.w3.org/2001/xml-events"
|
|
xmlns:xforms="http://www.w3.org/2002/xforms"
|
|
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
''' % {'urn': 'urn:oasis:names:tc:opendocument:xmlns:'}
|
|
|
|
_DOC_FONTS = '''\
|
|
<office:font-face-decls>
|
|
<style:font-face style:name="Nimbus Sans L"
|
|
svg:font-family="'Nimbus Sans L'"
|
|
style:font-family-generic="swiss"
|
|
style:font-pitch="variable"/>
|
|
<style:font-face style:name="DejaVu Sans"
|
|
svg:font-family="'DejaVu San'"
|
|
style:font-family-generic="system"
|
|
style:font-pitch="variable"/>
|
|
</office:font-face-decls>
|
|
'''
|
|
|
|
_DOC_STYLES = '''\
|
|
<office:automatic-styles>
|
|
<style:style style:name="co1"
|
|
style:family="table-column">
|
|
<style:table-column-properties
|
|
fo:break-before="auto"
|
|
style:column-width="3cm"/>
|
|
</style:style>
|
|
<style:style style:name="ro1"
|
|
style:family="table-row">
|
|
<style:table-row-properties
|
|
style:row-height="0.189in"
|
|
fo:break-before="auto"
|
|
style:use-optimal-row-height="true"/>
|
|
</style:style>
|
|
<style:style style:name="ta1"
|
|
style:family="table"
|
|
style:master-page-name="Default">
|
|
<style:table-properties
|
|
table:display="true"
|
|
style:writing-mode="lr-tb"/>
|
|
</style:style>
|
|
</office:automatic-styles>
|
|
'''
|
|
|
|
_STYLES_FONTS = '''\
|
|
<office:font-face-decls>
|
|
<style:font-face style:name="Times New Roman"
|
|
svg:font-family="'Times New Roman'"
|
|
style:font-family-generic="roman"
|
|
style:font-pitch="variable"/>
|
|
<style:font-face style:name="Arial"
|
|
svg:font-family="Arial"
|
|
style:font-family-generic="swiss"
|
|
style:font-pitch="variable"/>
|
|
</office:font-face-decls>
|
|
'''
|
|
|
|
_STYLES_STYLES = '''\
|
|
<office:styles>
|
|
<style:default-style style:family="table-cell">
|
|
<style:table-cell-properties
|
|
style:decimal-places="2"/>
|
|
<style:paragraph-properties
|
|
style:tab-stop-distance="0.2835inch"/>
|
|
<style:text-properties
|
|
style:font-name="Arial"/>
|
|
</style:default-style>
|
|
|
|
<style:style style:name="Default"
|
|
style:family="table-cell"
|
|
style:data-style-name="N0"/>
|
|
|
|
<style:default-style style:family="graphic">
|
|
<style:text-properties fo:color="#000000"
|
|
fo:font-family="'Times New Roman'"
|
|
style:font-style-name=""
|
|
style:font-family-generic="roman"
|
|
style:font-pitch="variable"
|
|
fo:font-size="12pt"
|
|
fo:language="none"
|
|
fo:country="none"
|
|
style:text-autospace="ideograph-alpha"
|
|
style:punctuation-wrap="simple"
|
|
style:line-break="strict"/>
|
|
</style:default-style>
|
|
</office:styles>
|
|
'''
|
|
_STYLES_AUTOMATIC = '''\
|
|
<office:automatic-styles>
|
|
<style:page-layout style:name="pm1">
|
|
<style:header-style>
|
|
<style:header-footer-properties
|
|
fo:min-height="0.2957inch"
|
|
fo:margin-left="0inch"
|
|
fo:margin-right="0inch"
|
|
fo:margin-bottom="0.0984inch"/>
|
|
</style:header-style>
|
|
<style:footer-style>
|
|
<style:header-footer-properties
|
|
fo:min-height="0.2957inch"
|
|
fo:margin-left="0inch"
|
|
fo:margin-right="0inch"
|
|
fo:margin-top="0.0984inch"/>
|
|
</style:footer-style>
|
|
</style:page-layout>
|
|
<style:page-layout style:name="pm2">
|
|
<style:header-style>
|
|
<style:header-footer-properties
|
|
fo:min-height="0.2957inch"
|
|
fo:margin-left="0inch"
|
|
fo:margin-right="0inch"
|
|
fo:margin-bottom="0.0984inch"
|
|
fo:border="0.0346inch solid #000000"
|
|
fo:border-top="0.0346inch solid #000000"
|
|
fo:border-bottom="0.0346inch solid #000000"
|
|
fo:border-left="0.0346inch solid #000000"
|
|
fo:border-right="0.0346inch solid #000000"
|
|
fo:padding="0.0071inch"
|
|
fo:padding-top="0.0071inch"
|
|
fo:padding-bottom="0.0071inch"
|
|
fo:padding-left="0.0071inch"
|
|
fo:padding-right="0.0071inch"
|
|
fo:background-color="#c0c0c0"/>
|
|
</style:header-style>
|
|
<style:footer-style>
|
|
<style:header-footer-properties
|
|
fo:min-height="0.2957inch"
|
|
fo:margin-left="0inch"
|
|
fo:margin-right="0inch"
|
|
fo:margin-top="0.0984inch"
|
|
fo:border="0.0346inch solid #000000"
|
|
fo:border-top="0.0346inch solid #000000"
|
|
fo:border-bottom="0.0346inch solid #000000"
|
|
fo:border-left="0.0346inch solid #000000"
|
|
fo:border-right="0.0346inch solid #000000"
|
|
fo:padding="0.0071inch"
|
|
fo:padding-top="0.0071inch"
|
|
fo:padding-bottom="0.0071inch"
|
|
fo:padding-left="0.0071inch"
|
|
fo:padding-right="0.0071inch"
|
|
fo:background-color="#c0c0c0"/>
|
|
</style:footer-style>
|
|
</style:page-layout>
|
|
</office:automatic-styles>
|
|
'''
|
|
|
|
_STYLES_MASTER = '''\
|
|
<office:master-styles>
|
|
<style:master-page style:name="Default"
|
|
style:page-layout-name="pm1">
|
|
<style:header>
|
|
<text:p>
|
|
<text:sheet-name>???</text:sheet-name>
|
|
</text:p>
|
|
</style:header>
|
|
<style:footer>
|
|
<text:p>Page
|
|
<text:page-number>1</text:page-number>
|
|
</text:p>
|
|
</style:footer>
|
|
</style:master-page>
|
|
<style:master-page style:name="Report"
|
|
style:page-layout-name="pm2">
|
|
<style:header>
|
|
<style:region-left>
|
|
<text:p>
|
|
<text:sheet-name>???</text:sheet-name>
|
|
(<text:file-name>???</text:file-name>)
|
|
</text:p>
|
|
</style:region-left>
|
|
<style:region-right>
|
|
<text:p>
|
|
<text:date style:data-style-name="N2"
|
|
text:date-value="2001-05-16">05/16/2001
|
|
</text:date>,
|
|
<text:time>10:53:17</text:time>
|
|
</text:p>
|
|
</style:region-right>
|
|
</style:header>
|
|
<style:footer>
|
|
<text:p>Page
|
|
<text:page-number>1</text:page-number> /
|
|
<text:page-count>99</text:page-count>
|
|
</text:p>
|
|
</style:footer>
|
|
</style:master-page>
|
|
</office:master-styles>
|
|
'''
|
|
|
|
_MANIFEST = '''\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<manifest:manifest
|
|
xmlns:manifest=
|
|
"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0">
|
|
<manifest:file-entry
|
|
manifest:media-type=
|
|
"application/vnd.oasis.opendocument.spreadsheet"
|
|
manifest:full-path="/"/>
|
|
<manifest:file-entry manifest:media-type=""
|
|
manifest:full-path="Pictures/"/>
|
|
<manifest:file-entry manifest:media-type="text/xml"
|
|
manifest:full-path="content.xml"/>
|
|
<manifest:file-entry manifest:media-type="text/xml"
|
|
manifest:full-path="styles.xml"/>
|
|
<manifest:file-entry manifest:media-type="text/xml"
|
|
manifest:full-path="meta.xml"/>
|
|
</manifest:manifest>
|
|
'''
|
|
|
|
_META = '''\
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<office:document-meta
|
|
xmlns:office=
|
|
"urn:oasis:names:tc:opendocument:xmlns:office:1.0"
|
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
xmlns:meta=
|
|
"urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
|
|
office:class="text" office:version="1.0">
|
|
<office:meta>
|
|
<meta:generator>
|
|
%(program)s %(version)s
|
|
</meta:generator>
|
|
<meta:initial-creator>
|
|
%(name)s
|
|
</meta:initial-creator>
|
|
<meta:creation-date>
|
|
%(time)s
|
|
</meta:creation-date>
|
|
<dc:creator>
|
|
%(name)s
|
|
</dc:creator>
|
|
<dc:date>
|
|
%(time)s
|
|
</dc:date>
|
|
<meta:print-date>
|
|
0-00-00T00:00:00
|
|
</meta:print-date>
|
|
<dc:language>en-US</dc:language>
|
|
<meta:editing-cycles>1</meta:editing-cycles>
|
|
<meta:editing-duration>PT0S</meta:editing-duration>
|
|
<meta:user-defined meta:name="Info 0"/>
|
|
<meta:user-defined meta:name="Info 1"/>
|
|
<meta:user-defined meta:name="Info 2"/>
|
|
<meta:user-defined meta:name="Info 3"/>
|
|
</office:meta>
|
|
</office:document-meta>
|
|
'''
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# ODSTab
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
class ODSTab(TabbedDoc):
|
|
|
|
def __init__(self, columns):
|
|
TabbedDoc.__init__(self, columns)
|
|
self.f = None
|
|
self.filename = None
|
|
self.level = 0
|
|
self.time = "0000-00-00T00:00:00"
|
|
|
|
def open(self,filename):
|
|
import time
|
|
|
|
t = time.localtime(time.time())
|
|
self.time = "%04d-%02d-%02dT%02d:%02d:%02d" % t[:6]
|
|
|
|
self.filename = filename
|
|
if not filename.endswith('.ods'):
|
|
self.filename += '.ods'
|
|
|
|
try:
|
|
self.content_xml = tempfile.mktemp()
|
|
self.f = open(self.content_xml,"wb")
|
|
except IOError as msg:
|
|
raise ReportError(_("Could not create %s") % self.content_xml, msg)
|
|
except:
|
|
raise ReportError(_("Could not create %s") % self.content_xml)
|
|
|
|
self.f = open(self.content_xml,"w", encoding='utf-8')
|
|
self.f.write(
|
|
'<?xml version="1.0" encoding="UTF-8"?>\n' +
|
|
'<office:document-content ' +
|
|
_XMLNS +
|
|
'office:version="1.0"> ' +
|
|
'<office:script/>\n'
|
|
)
|
|
|
|
self.f.write(_DOC_FONTS)
|
|
self.f.write(_DOC_STYLES)
|
|
self.f.write(
|
|
'<office:body>\n'
|
|
'<office:spreadsheet>\n')
|
|
|
|
def close(self):
|
|
self.f.write(
|
|
'</office:spreadsheet>\n'
|
|
'</office:body>\n'
|
|
'</office:document-content>\n'
|
|
)
|
|
self.f.close()
|
|
self._write_styles_file()
|
|
self._write_manifest()
|
|
self._write_meta_file()
|
|
self._write_mimetype_file()
|
|
self._write_zip()
|
|
|
|
def start_row(self):
|
|
self.f.write('<table:table-row table:style-name="')
|
|
self.f.write('ro1')
|
|
self.f.write('">\n')
|
|
|
|
def end_row(self):
|
|
self.f.write('</table:table-row>\n')
|
|
|
|
def write_cell(self, text):
|
|
self.f.write('<table:table-cell office:value-type="string">')
|
|
self.f.write('>\n')
|
|
|
|
self.f.write('<text:p>')
|
|
if text is not None: # it must not be just 'if text'
|
|
text = text.replace('&','&') # Must be first
|
|
text = text.replace('<','<')
|
|
text = text.replace('>','>')
|
|
text = text.replace('\t','<text:tab-stop/>')
|
|
text = text.replace('\n','<text:line-break/>')
|
|
self.f.write(str(text))
|
|
|
|
self.f.write('</text:p>\n')
|
|
self.f.write('</table:table-cell>\n')
|
|
# for col in range(1,self.span):
|
|
# self.f.write('<table:covered-table-cell/>\n')
|
|
|
|
def _write_zip(self):
|
|
try:
|
|
file = zipfile.ZipFile(self.filename,"w",zipfile.ZIP_DEFLATED)
|
|
except IOError as msg:
|
|
errmsg = "%s\n%s" % (_("Could not create %s") % self.filename, msg)
|
|
raise ReportError(errmsg)
|
|
except:
|
|
raise ReportError(_("Could not create %s") % self.filename)
|
|
|
|
file.write(self.manifest_xml,str("META-INF/manifest.xml"))
|
|
file.write(self.content_xml,str("content.xml"))
|
|
file.write(self.meta_xml,str("meta.xml"))
|
|
file.write(self.styles_xml,str("styles.xml"))
|
|
file.write(self.mimetype,str("mimetype"))
|
|
file.close()
|
|
|
|
os.unlink(self.manifest_xml)
|
|
os.unlink(self.content_xml)
|
|
os.unlink(self.meta_xml)
|
|
os.unlink(self.styles_xml)
|
|
|
|
def _write_styles_file(self):
|
|
self.styles_xml = tempfile.mktemp()
|
|
|
|
try:
|
|
self.f = open(self.styles_xml,"wb")
|
|
except IOError as msg:
|
|
errmsg = "%s\n%s" % (_("Could not create %s") % self.styles_xml, msg)
|
|
raise ReportError(errmsg)
|
|
except:
|
|
raise ReportError(_("Could not create %s") % self.styles_xml)
|
|
|
|
self.f = open(self.styles_xml,"w")
|
|
self.f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
|
|
self.f.write(
|
|
'<office:document-styles ' +
|
|
_XMLNS +
|
|
'office:version="1.0"> '
|
|
)
|
|
self.f.write(_STYLES_FONTS)
|
|
self.f.write(_STYLES_STYLES)
|
|
self.f.write(_STYLES_AUTOMATIC)
|
|
self.f.write(_STYLES_MASTER)
|
|
|
|
self.f.write('</office:document-styles>\n')
|
|
self.f.close()
|
|
|
|
def start_page(self):
|
|
self.f.write('<table:table table:name="ta1">')
|
|
for col in range(0,self.columns):
|
|
self.f.write('<table:table-column table:style-name="co1"/>\n')
|
|
|
|
def end_page(self):
|
|
self.f.write('</table:table>\n')
|
|
|
|
def _write_manifest(self):
|
|
self.manifest_xml = tempfile.mktemp()
|
|
|
|
try:
|
|
self.f = open(self.manifest_xml,"wb")
|
|
except IOError as msg:
|
|
errmsg = "%s\n%s" % (_("Could not create %s") % self.manifest_xml, msg)
|
|
raise ReportError(errmsg)
|
|
except:
|
|
raise ReportError(_("Could not create %s") % self.manifest_xml)
|
|
|
|
self.f = open(self.manifest_xml,"w")
|
|
self.f.write(_MANIFEST)
|
|
self.f.close()
|
|
|
|
def _write_meta_file(self):
|
|
self.meta_xml = tempfile.mktemp()
|
|
|
|
try:
|
|
self.f = open(self.meta_xml,"wb")
|
|
except IOError as msg:
|
|
errmsg = "%s\n%s" % (_("Could not create %s") % self.meta_xml, msg)
|
|
raise ReportError(errmsg)
|
|
except:
|
|
raise ReportError(_("Could not create %s") % self.meta_xml)
|
|
|
|
self.f = open(self.meta_xml,"w")
|
|
|
|
self.f.write(_META %
|
|
{'program': PROGRAM_NAME,
|
|
'version': VERSION,
|
|
'name' : self.name,
|
|
'time' : self.time,
|
|
}
|
|
)
|
|
self.f.close()
|
|
|
|
def _write_mimetype_file(self):
|
|
self.mimetype = tempfile.mktemp()
|
|
|
|
try:
|
|
self.f = open(self.mimetype,"wb")
|
|
except IOError as msg:
|
|
errmsg = "%s\n%s" % (_("Could not create %s") % self.mimetype, msg)
|
|
raise ReportError(errmsg)
|
|
except:
|
|
raise ReportError(_("Could not create %s") % self.mimetype)
|
|
|
|
self.f = open(self.mimetype,"w")
|
|
self.f.write('application/vnd.oasis.opendocument.spreadsheet')
|
|
self.f.close()
|
|
|
|
if __name__ == "__main__":
|
|
|
|
file = ODSTab(3)
|
|
file.open("test")
|
|
file.start_page()
|
|
for i in [ ('one', 'two', 'three'), ('fo"ur', 'fi,ve', 'six') ]:
|
|
file.start_row()
|
|
for j in i:
|
|
file.write_cell(j)
|
|
file.end_row()
|
|
file.end_page()
|
|
file.close()
|