More input and output formats for OO conversion in converter.py and bugfix in skyn edit.
This commit is contained in:
parent
fff2b6a329
commit
e89eda4838
|
@ -355,7 +355,7 @@ class Ref(Type):
|
||||||
|
|
||||||
class Computed(Type):
|
class Computed(Type):
|
||||||
def __init__(self, validator=None, multiplicity=(0,1), index=None,
|
def __init__(self, validator=None, multiplicity=(0,1), index=None,
|
||||||
default=None, optional=False, editDefault=False, show=True,
|
default=None, optional=False, editDefault=False, show='view',
|
||||||
page='main', group=None, move=0, indexed=False,
|
page='main', group=None, move=0, indexed=False,
|
||||||
searchable=False, specificReadPermission=False,
|
searchable=False, specificReadPermission=False,
|
||||||
specificWritePermission=False, width=None, height=None,
|
specificWritePermission=False, width=None, height=None,
|
||||||
|
|
|
@ -33,9 +33,13 @@ class AbstractMixin:
|
||||||
# creates the final object from the temp object.
|
# creates the final object from the temp object.
|
||||||
previousData = None
|
previousData = None
|
||||||
if not created: previousData = self.rememberPreviousData()
|
if not created: previousData = self.rememberPreviousData()
|
||||||
# We do not process form data (=real update on the object) if the tool
|
# Perform the change on the object, unless self is a tool being created.
|
||||||
# itself is being created.
|
if (obj._appy_meta_type == 'tool') and created:
|
||||||
if obj._appy_meta_type != 'tool': obj.processForm()
|
# We do not process form data (=real update on the object) if the
|
||||||
|
# tool itself is being created.
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
obj.processForm()
|
||||||
if previousData:
|
if previousData:
|
||||||
# Keep in history potential changes on historized fields
|
# Keep in history potential changes on historized fields
|
||||||
self.historizeData(previousData)
|
self.historizeData(previousData)
|
||||||
|
@ -389,7 +393,7 @@ class AbstractMixin:
|
||||||
fieldDescr = fieldDescr.__dict__
|
fieldDescr = fieldDescr.__dict__
|
||||||
appyType = fieldDescr['appyType']
|
appyType = fieldDescr['appyType']
|
||||||
if isEdit and (appyType['type']=='Ref') and appyType['add']:return False
|
if isEdit and (appyType['type']=='Ref') and appyType['add']:return False
|
||||||
if isEdit and (appyType['type'] in ('Action', 'Computed')): return False
|
if isEdit and (appyType['type'] == 'Action'): return False
|
||||||
if (fieldDescr['widgetType'] == 'backField') and \
|
if (fieldDescr['widgetType'] == 'backField') and \
|
||||||
not self.getBRefs(fieldDescr['fieldRel']): return False
|
not self.getBRefs(fieldDescr['fieldRel']): return False
|
||||||
# Do not show field if it is optional and not selected in flavour
|
# Do not show field if it is optional and not selected in flavour
|
||||||
|
|
|
@ -3,23 +3,19 @@
|
||||||
errors request/errors | python:{};
|
errors request/errors | python:{};
|
||||||
Iterator python:modules['Products.Archetypes'].IndexIterator;
|
Iterator python:modules['Products.Archetypes'].IndexIterator;
|
||||||
schematas contextObj/Schemata;
|
schematas contextObj/Schemata;
|
||||||
fieldsets python:[key for key in schematas.keys() if (key != 'metadata') and (schematas[key].editableFields(here, visible_only=True))];
|
fieldsets python:[key for key in schematas.keys() if (key != 'metadata') and (schematas[key].editableFields(contextObj, visible_only=True))];
|
||||||
default_fieldset python:(not schematas or schematas.has_key('default')) and 'default' or fieldsets[0];
|
default_fieldset python:(not schematas or schematas.has_key('default')) and 'default' or fieldsets[0];
|
||||||
fieldset request/fieldset|options/fieldset|default_fieldset;
|
fieldset request/fieldset|options/fieldset|default_fieldset;
|
||||||
fields python:schematas[fieldset].editableFields(here);
|
fields python:schematas[fieldset].editableFields(contextObj);
|
||||||
dummy python:here.at_isEditable(fields);
|
lockable python:hasattr(contextObj, 'wl_isLocked');
|
||||||
portal_type python:here.getPortalTypeName().lower().replace(' ', '_');
|
isLocked python:lockable and contextObj.wl_isLocked();
|
||||||
type_name here/getPortalTypeName|here/archetype_name;
|
|
||||||
lockable python:hasattr(here, 'wl_isLocked');
|
|
||||||
isLocked python:lockable and here.wl_isLocked();
|
|
||||||
tabindex tabindex|python:Iterator(pos=7000);
|
|
||||||
isEdit python:True;
|
isEdit python:True;
|
||||||
tool contextObj/getTool;
|
tool contextObj/getTool;
|
||||||
flavour python: tool.getFlavour(contextObj);
|
flavour python: tool.getFlavour(contextObj);
|
||||||
appFolder tool/getAppFolder;
|
appFolder tool/getAppFolder;
|
||||||
appName appFolder/id;
|
appName appFolder/id;
|
||||||
css python:here.getUniqueWidgetAttr(fields, 'helper_css');
|
css python:contextObj.getUniqueWidgetAttr(fields, 'helper_css');
|
||||||
js python:here.getUniqueWidgetAttr(fields, 'helper_js');
|
js python:contextObj.getUniqueWidgetAttr(fields, 'helper_js');
|
||||||
phaseInfo python: contextObj.getAppyPhases(fieldset=fieldset, forPlone=True);
|
phaseInfo python: contextObj.getAppyPhases(fieldset=fieldset, forPlone=True);
|
||||||
phase request/phase|phaseInfo/name;
|
phase request/phase|phaseInfo/name;
|
||||||
pageName python: contextObj.getAppyPage(isEdit, phaseInfo);">
|
pageName python: contextObj.getAppyPage(isEdit, phaseInfo);">
|
||||||
|
@ -91,24 +87,20 @@
|
||||||
<tal:previousButton condition="python: pageIndex > 0">
|
<tal:previousButton condition="python: pageIndex > 0">
|
||||||
<input class="context" type="submit" name="buttonPrevious"
|
<input class="context" type="submit" name="buttonPrevious"
|
||||||
i18n:attributes="value label_previous;" i18n:domain="plone"
|
i18n:attributes="value label_previous;" i18n:domain="plone"
|
||||||
tal:attributes="tabindex tabindex/next;
|
tal:attributes="disabled python:test(isLocked, 'disabled', None);"/>
|
||||||
disabled python:test(isLocked, 'disabled', None);"/>
|
|
||||||
<input type="hidden" name="previousPage" tal:attributes="value python: pages[pageIndex-1]"/>
|
<input type="hidden" name="previousPage" tal:attributes="value python: pages[pageIndex-1]"/>
|
||||||
</tal:previousButton>
|
</tal:previousButton>
|
||||||
<tal:nextButton condition="python: pageIndex < numberOfPages - 1">
|
<tal:nextButton condition="python: pageIndex < numberOfPages - 1">
|
||||||
<input class="context" type="submit" name="buttonNext" value="Next"
|
<input class="context" type="submit" name="buttonNext" value="Next"
|
||||||
i18n:attributes="value label_next;" i18n:domain="plone"
|
i18n:attributes="value label_next;" i18n:domain="plone"
|
||||||
tal:attributes="tabindex tabindex/next;
|
tal:attributes="disabled python:test(isLocked, 'disabled', None);"/>
|
||||||
disabled python:test(isLocked, 'disabled', None);"/>
|
|
||||||
<input type="hidden" name="nextPage" tal:attributes="value python: pages[pageIndex+1]"/>
|
<input type="hidden" name="nextPage" tal:attributes="value python: pages[pageIndex+1]"/>
|
||||||
</tal:nextButton>
|
</tal:nextButton>
|
||||||
<input class="context" type="submit" name="buttonOk"
|
<input class="context" type="submit" name="buttonOk"
|
||||||
i18n:attributes="value label_save;" i18n:domain="plone"
|
i18n:attributes="value label_save;" i18n:domain="plone"
|
||||||
tal:attributes="tabindex tabindex/next;
|
tal:attributes="disabled python:test(isLocked, 'disabled', None);"/>
|
||||||
disabled python:test(isLocked, 'disabled', None);"/>
|
|
||||||
<input class="standalone" type="submit" name="buttonCancel"
|
<input class="standalone" type="submit" name="buttonCancel"
|
||||||
i18n:attributes="value label_cancel;" i18n:domain="plone"
|
i18n:attributes="value label_cancel;" i18n:domain="plone"/>
|
||||||
tal:attributes="tabindex tabindex/next"/>
|
|
||||||
</metal:block>
|
</metal:block>
|
||||||
</form>
|
</form>
|
||||||
<div metal:use-macro="here/skyn/macros/macros/showPageFooter"/>
|
<div metal:use-macro="here/skyn/macros/macros/showPageFooter"/>
|
||||||
|
|
|
@ -202,7 +202,7 @@
|
||||||
<metal:editRef use-macro="here/skyn/ref/macros/editReference" />
|
<metal:editRef use-macro="here/skyn/ref/macros/editReference" />
|
||||||
</tal:ref>
|
</tal:ref>
|
||||||
</tal:editRef>
|
</tal:editRef>
|
||||||
<tal:computedField condition="python: (not isEdit) and (appyType['type'] == 'Computed')">
|
<tal:computedField condition="python: appyType['type'] == 'Computed'">
|
||||||
<metal:cf use-macro="here/skyn/macros/macros/showComputedField" />
|
<metal:cf use-macro="here/skyn/macros/macros/showComputedField" />
|
||||||
</tal:computedField>
|
</tal:computedField>
|
||||||
<tal:actionField condition="python: appyType['type'] == 'Action'">
|
<tal:actionField condition="python: appyType['type'] == 'Action'">
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
developer the real classes used by the underlying web framework.'''
|
developer the real classes used by the underlying web framework.'''
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import time, os.path, mimetypes, unicodedata, random
|
import os, os.path, time, mimetypes, unicodedata, random
|
||||||
|
import appy.pod
|
||||||
from appy.gen import Search
|
from appy.gen import Search
|
||||||
from appy.gen.utils import sequenceTypes
|
from appy.gen.utils import sequenceTypes
|
||||||
from appy.shared.utils import getOsTempFolder
|
from appy.shared.utils import getOsTempFolder
|
||||||
|
@ -236,15 +237,23 @@ class AbstractWrapper:
|
||||||
wfTool.doActionFor(self.o, transitionName, comment=comment)
|
wfTool.doActionFor(self.o, transitionName, comment=comment)
|
||||||
del self.o._v_appy_do
|
del self.o._v_appy_do
|
||||||
|
|
||||||
def log(self, message, logLevel='info'):
|
def log(self, message, type='info'):
|
||||||
'''Logs a message in the log file. p_logLevel may be "info", "warning"
|
'''Logs a message in the log file. p_logLevel may be "info", "warning"
|
||||||
or "error".'''
|
or "error".'''
|
||||||
logger = self.o.getProductConfig().logger
|
logger = self.o.getProductConfig().logger
|
||||||
if logLevel == 'warning': logMethod = logger.warn
|
if type == 'warning': logMethod = logger.warn
|
||||||
elif logLevel == 'error': logMethod = logger.error
|
elif type == 'error': logMethod = logger.error
|
||||||
else: logMethod = logger.info
|
else: logMethod = logger.info
|
||||||
logMethod(message)
|
logMethod(message)
|
||||||
|
|
||||||
|
def say(self, message, type='info'):
|
||||||
|
'''Prints a message in the user interface. p_logLevel may be "info",
|
||||||
|
"warning" or "error".'''
|
||||||
|
mType = type
|
||||||
|
if mType == 'warning': mType = 'warn'
|
||||||
|
elif mType == 'error': mType = 'stop'
|
||||||
|
self.o.plone_utils.addPortalMessage(message, type=mType)
|
||||||
|
|
||||||
def normalize(self, s):
|
def normalize(self, s):
|
||||||
'''Returns a version of string p_s whose special chars have been
|
'''Returns a version of string p_s whose special chars have been
|
||||||
replaced with normal chars.'''
|
replaced with normal chars.'''
|
||||||
|
@ -338,11 +347,16 @@ class FileWrapper:
|
||||||
raise 'Impossible to set attribute %s. "Settable" attributes ' \
|
raise 'Impossible to set attribute %s. "Settable" attributes ' \
|
||||||
'are "name", "content" and "mimeType".' % name
|
'are "name", "content" and "mimeType".' % name
|
||||||
|
|
||||||
def dump(self, filePath=None):
|
def dump(self, filePath=None, format=None, tool=None):
|
||||||
'''Writes the file on disk. If p_filePath is specified, it is the
|
'''Writes the file on disk. If p_filePath is specified, it is the
|
||||||
path name where the file will be dumped; folders mentioned in it
|
path name where the file will be dumped; folders mentioned in it
|
||||||
must exist. If not, the file will be dumped in the OS temp folder.
|
must exist. If not, the file will be dumped in the OS temp folder.
|
||||||
The absolute path name of the dumped file is returned.'''
|
The absolute path name of the dumped file is returned.
|
||||||
|
If an error occurs, the method returns None. If p_format is
|
||||||
|
specified, OpenOffice will be called for converting the dumped file
|
||||||
|
to the desired format. In this case, p_tool, a Appy tool, must be
|
||||||
|
provided. Indeed, any Appy tool contains parameters for contacting
|
||||||
|
OpenOffice in server mode.'''
|
||||||
if not filePath:
|
if not filePath:
|
||||||
filePath = '%s/file%f.%s' % (getOsTempFolder(), time.time(),
|
filePath = '%s/file%f.%s' % (getOsTempFolder(), time.time(),
|
||||||
self.name)
|
self.name)
|
||||||
|
@ -358,5 +372,20 @@ class FileWrapper:
|
||||||
# Only one chunk
|
# Only one chunk
|
||||||
f.write(self.content)
|
f.write(self.content)
|
||||||
f.close()
|
f.close()
|
||||||
|
if format:
|
||||||
|
if not tool: return
|
||||||
|
# Convert the dumped file using OpenOffice
|
||||||
|
convScript = '%s/converter.py' % os.path.dirname(appy.pod.__file__)
|
||||||
|
cmd = '%s %s "%s" %s -p%d' % (tool.unoEnabledPython, convScript,
|
||||||
|
filePath, format, tool.openOfficePort)
|
||||||
|
res = os.system(cmd)
|
||||||
|
os.remove(filePath)
|
||||||
|
if res != 0: return
|
||||||
|
# Return the name of the converted file.
|
||||||
|
baseName, ext = os.path.splitext(filePath)
|
||||||
|
if (ext == '.%s' % format):
|
||||||
|
filePath = '%s.res.%s' % (baseName, format)
|
||||||
|
else:
|
||||||
|
filePath = '%s.%s' % (baseName, format)
|
||||||
return filePath
|
return filePath
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
212
pod/converter.py
212
pod/converter.py
|
@ -20,15 +20,26 @@
|
||||||
import sys, os, os.path, time, signal
|
import sys, os, os.path, time, signal
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
|
|
||||||
ODT_FILE_TYPES = {'doc': 'MS Word 97', # Could be 'MS Word 2003 XML'
|
htmlFilters = {'odt': 'HTML (StarWriter)',
|
||||||
'pdf': 'writer_pdf_Export',
|
'ods': 'HTML (StarCalc)',
|
||||||
'rtf': 'Rich Text Format',
|
'odp': 'impress_html_Export'}
|
||||||
'txt': 'Text',
|
|
||||||
'html': 'HTML (StarWriter)',
|
FILE_TYPES = {'odt': 'writer8',
|
||||||
'htm': 'HTML (StarWriter)',
|
'ods': 'calc8',
|
||||||
'odt': 'ODT'}
|
'odp': 'impress8',
|
||||||
# Conversion to ODT does not make any conversion; it simply updates indexes and
|
'htm': htmlFilters, 'html': htmlFilters,
|
||||||
# linked documents.
|
'rtf': 'Rich Text Format',
|
||||||
|
'txt': 'Text',
|
||||||
|
'csv': 'Text - txt - csv (StarCalc)',
|
||||||
|
'pdf': {'odt': 'writer_pdf_Export', 'ods': 'calc_pdf_Export',
|
||||||
|
'odp': 'impress_pdf_Export', 'odg': 'draw_pdf_Export'},
|
||||||
|
'swf': 'impress_flash_Export',
|
||||||
|
'doc': 'MS Word 97',
|
||||||
|
'xls': 'MS Excel 97',
|
||||||
|
'ppt': 'MS PowerPoint 97',
|
||||||
|
}
|
||||||
|
# Conversion from odt to odt does not make any conversion, but updates indexes
|
||||||
|
# and linked documents.
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class ConverterError(Exception): pass
|
class ConverterError(Exception): pass
|
||||||
|
@ -46,7 +57,7 @@ DEFAULT_PORT = 2002
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
class Converter:
|
class Converter:
|
||||||
'''Converts an ODT document into pdf, doc, txt or rtf.'''
|
'''Converts an document readable by OpenOffice into pdf, doc, txt or rtf.'''
|
||||||
exeVariants = ('soffice.exe', 'soffice')
|
exeVariants = ('soffice.exe', 'soffice')
|
||||||
pathReplacements = {'program files': 'progra~1',
|
pathReplacements = {'program files': 'progra~1',
|
||||||
'openoffice.org 1': 'openof~1',
|
'openoffice.org 1': 'openof~1',
|
||||||
|
@ -54,41 +65,64 @@ class Converter:
|
||||||
}
|
}
|
||||||
def __init__(self, docPath, resultType, port=DEFAULT_PORT):
|
def __init__(self, docPath, resultType, port=DEFAULT_PORT):
|
||||||
self.port = port
|
self.port = port
|
||||||
self.docUrl, self.docPath = self.getDocUrls(docPath)
|
self.docUrl, self.docPath = self.getInputUrls(docPath)
|
||||||
self.resultFilter = self.getResultFilter(resultType)
|
self.inputType = os.path.splitext(docPath)[1][1:].lower()
|
||||||
self.resultUrl = self.getResultUrl(resultType)
|
self.resultType = resultType
|
||||||
|
self.resultFilter = self.getResultFilter()
|
||||||
|
self.resultUrl = self.getResultUrl()
|
||||||
self.ooContext = None
|
self.ooContext = None
|
||||||
self.oo = None # OpenOffice application object
|
self.oo = None # The OpenOffice application object
|
||||||
self.doc = None # OpenOffice loaded document
|
self.doc = None # The OpenOffice loaded document
|
||||||
def getDocUrls(self, docPath):
|
|
||||||
|
def getInputUrls(self, docPath):
|
||||||
|
'''Returns the absolute path of the input file. In fact, it returns a
|
||||||
|
tuple with some URL version of the path for OO as the first element
|
||||||
|
and the absolute path as the second element.'''
|
||||||
import uno
|
import uno
|
||||||
if not os.path.exists(docPath) and not os.path.isfile(docPath):
|
if not os.path.exists(docPath) and not os.path.isfile(docPath):
|
||||||
raise ConverterError(DOC_NOT_FOUND % docPath)
|
raise ConverterError(DOC_NOT_FOUND % docPath)
|
||||||
docAbsPath = os.path.abspath(docPath)
|
docAbsPath = os.path.abspath(docPath)
|
||||||
# Return one path for OO, one path for me.
|
# Return one path for OO, one path for me.
|
||||||
return uno.systemPathToFileUrl(docAbsPath), docAbsPath
|
return uno.systemPathToFileUrl(docAbsPath), docAbsPath
|
||||||
def getResultFilter(self, resultType):
|
|
||||||
if ODT_FILE_TYPES.has_key(resultType):
|
def getResultFilter(self):
|
||||||
res = ODT_FILE_TYPES[resultType]
|
'''Based on the result type, identifies which OO filter to use for the
|
||||||
|
document conversion.'''
|
||||||
|
if FILE_TYPES.has_key(self.resultType):
|
||||||
|
res = FILE_TYPES[self.resultType]
|
||||||
|
if isinstance(res, dict):
|
||||||
|
res = res[self.inputType]
|
||||||
else:
|
else:
|
||||||
raise ConverterError(BAD_RESULT_TYPE % (resultType,
|
raise ConverterError(BAD_RESULT_TYPE % (self.resultType,
|
||||||
ODT_FILE_TYPES.keys()))
|
FILE_TYPES.keys()))
|
||||||
return res
|
return res
|
||||||
def getResultUrl(self, resultType):
|
|
||||||
|
def getResultUrl(self):
|
||||||
|
'''Returns the path of the result file in the format needed by OO. If
|
||||||
|
the result type and the input type are the same (ie the user wants to
|
||||||
|
refresh indexes or some other action and not perform a real
|
||||||
|
conversion), the result file is named
|
||||||
|
<inputFileName>.res.<resultType>.
|
||||||
|
|
||||||
|
Else, the result file is named like the input file but with a
|
||||||
|
different extension:
|
||||||
|
<inputFileName>.<resultType>
|
||||||
|
'''
|
||||||
import uno
|
import uno
|
||||||
baseName = os.path.splitext(self.docPath)[0]
|
baseName = os.path.splitext(self.docPath)[0]
|
||||||
if resultType != 'odt':
|
if self.resultType != self.inputType:
|
||||||
res = '%s.%s' % (baseName, resultType)
|
res = '%s.%s' % (baseName, self.resultType)
|
||||||
else:
|
else:
|
||||||
res = '%s.res.%s' % (baseName, resultType)
|
res = '%s.res.%s' % (baseName, self.resultType)
|
||||||
try:
|
try:
|
||||||
f = open(res, 'w')
|
f = open(res, 'w')
|
||||||
f.write('Hello')
|
f.write('Hello')
|
||||||
f.close()
|
f.close()
|
||||||
os.remove(res)
|
os.remove(res)
|
||||||
return uno.systemPathToFileUrl(res)
|
return uno.systemPathToFileUrl(res)
|
||||||
except OSError, oe:
|
except (OSError, IOError), ioe:
|
||||||
raise ConverterError(CANNOT_WRITE_RESULT % (res, oe))
|
raise ConverterError(CANNOT_WRITE_RESULT % (res, ioe))
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
'''Connects to OpenOffice'''
|
'''Connects to OpenOffice'''
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
|
@ -115,73 +149,90 @@ class Converter:
|
||||||
'com.sun.star.frame.Desktop', self.ooContext)
|
'com.sun.star.frame.Desktop', self.ooContext)
|
||||||
except NoConnectException, nce:
|
except NoConnectException, nce:
|
||||||
raise ConverterError(CONNECT_ERROR % (self.port, nce))
|
raise ConverterError(CONNECT_ERROR % (self.port, nce))
|
||||||
def disconnect(self):
|
|
||||||
self.doc.close(True)
|
def updateOdtDocument(self):
|
||||||
# Do a nasty thing before exiting the python process. In case the
|
'''If the input file is an ODT document, we will perform 2 tasks:
|
||||||
# last call is a oneway call (e.g. see idl-spec of insertString),
|
1) Update all annexes;
|
||||||
# it must be forced out of the remote-bridge caches before python
|
2) Update sections (if sections refer to external content, we try to
|
||||||
# exits the process. Otherwise, the oneway call may or may not reach
|
include the content within the result file)
|
||||||
# the target object.
|
'''
|
||||||
# I do this here by calling a cheap synchronous call (getPropertyValue).
|
from com.sun.star.lang import IndexOutOfBoundsException
|
||||||
self.ooContext.ServiceManager
|
|
||||||
def loadDocument(self):
|
|
||||||
from com.sun.star.lang import IllegalArgumentException, \
|
|
||||||
IndexOutOfBoundsException
|
|
||||||
# I need to use IndexOutOfBoundsException because sometimes, when
|
# I need to use IndexOutOfBoundsException because sometimes, when
|
||||||
# using sections.getCount, UNO returns a number that is bigger than
|
# using sections.getCount, UNO returns a number that is bigger than
|
||||||
# the real number of sections (this is because it also counts the
|
# the real number of sections (this is because it also counts the
|
||||||
# sections that are present within the sub-documents to integrate)
|
# sections that are present within the sub-documents to integrate)
|
||||||
|
# Update all indexes
|
||||||
|
indexes = self.doc.getDocumentIndexes()
|
||||||
|
indexesCount = indexes.getCount()
|
||||||
|
if indexesCount != 0:
|
||||||
|
for i in range(indexesCount):
|
||||||
|
try:
|
||||||
|
indexes.getByIndex(i).update()
|
||||||
|
except IndexOutOfBoundsException:
|
||||||
|
pass
|
||||||
|
# Update sections
|
||||||
|
self.doc.updateLinks()
|
||||||
|
sections = self.doc.getTextSections()
|
||||||
|
sectionsCount = sections.getCount()
|
||||||
|
if sectionsCount != 0:
|
||||||
|
for i in range(sectionsCount-1, -1, -1):
|
||||||
|
# I must walk into the section from last one to the first
|
||||||
|
# one. Else, when "disposing" sections, I remove sections
|
||||||
|
# and the remaining sections other indexes.
|
||||||
|
try:
|
||||||
|
section = sections.getByIndex(i)
|
||||||
|
if section.FileLink and section.FileLink.FileURL:
|
||||||
|
section.dispose() # This method removes the
|
||||||
|
# <section></section> tags without removing the content
|
||||||
|
# of the section. Else, it won't appear.
|
||||||
|
except IndexOutOfBoundsException:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def loadDocument(self):
|
||||||
|
from com.sun.star.lang import IllegalArgumentException, \
|
||||||
|
IndexOutOfBoundsException
|
||||||
from com.sun.star.beans import PropertyValue
|
from com.sun.star.beans import PropertyValue
|
||||||
try:
|
try:
|
||||||
# Load the document to convert in a new hidden frame
|
# Loads the document to convert in a new hidden frame
|
||||||
prop = PropertyValue()
|
prop = PropertyValue()
|
||||||
prop.Name = 'Hidden'
|
prop.Name = 'Hidden'
|
||||||
prop.Value = True
|
prop.Value = True
|
||||||
self.doc = self.oo.loadComponentFromURL(self.docUrl, "_blank", 0,
|
self.doc = self.oo.loadComponentFromURL(self.docUrl, "_blank", 0,
|
||||||
(prop,))
|
(prop,))
|
||||||
# Update all indexes
|
if self.inputType == 'odt':
|
||||||
indexes = self.doc.getDocumentIndexes()
|
# Perform additional tasks for odt documents
|
||||||
indexesCount = indexes.getCount()
|
self.updateOdtDocument()
|
||||||
if indexesCount != 0:
|
try:
|
||||||
for i in range(indexesCount):
|
self.doc.refresh()
|
||||||
try:
|
except AttributeError:
|
||||||
indexes.getByIndex(i).update()
|
pass
|
||||||
except IndexOutOfBoundsException:
|
|
||||||
pass
|
|
||||||
# Update sections
|
|
||||||
self.doc.updateLinks()
|
|
||||||
sections = self.doc.getTextSections()
|
|
||||||
sectionsCount = sections.getCount()
|
|
||||||
if sectionsCount != 0:
|
|
||||||
for i in range(sectionsCount-1, -1, -1):
|
|
||||||
# I must walk into the section from last one to the first
|
|
||||||
# one. Else, when "disposing" sections, I remove sections
|
|
||||||
# and the remaining sections other indexes.
|
|
||||||
try:
|
|
||||||
section = sections.getByIndex(i)
|
|
||||||
if section.FileLink and section.FileLink.FileURL:
|
|
||||||
section.dispose() # This method removes the
|
|
||||||
# <section></section> tags without removing the content
|
|
||||||
# of the section. Else, it won't appear.
|
|
||||||
except IndexOutOfBoundsException:
|
|
||||||
pass
|
|
||||||
except IllegalArgumentException, iae:
|
except IllegalArgumentException, iae:
|
||||||
raise ConverterError(URL_NOT_FOUND % (self.docPath, iae))
|
raise ConverterError(URL_NOT_FOUND % (self.docPath, iae))
|
||||||
|
|
||||||
def convertDocument(self):
|
def convertDocument(self):
|
||||||
if self.resultFilter != 'ODT':
|
'''Calls OO to perform a document conversion. Note that the conversion
|
||||||
# I must really perform a conversion
|
is not really done if the source and target documents have the same
|
||||||
from com.sun.star.beans import PropertyValue
|
type.'''
|
||||||
prop = PropertyValue()
|
properties = []
|
||||||
prop.Name = 'FilterName'
|
from com.sun.star.beans import PropertyValue
|
||||||
prop.Value = self.resultFilter
|
prop = PropertyValue()
|
||||||
self.doc.storeToURL(self.resultUrl, (prop,))
|
prop.Name = 'FilterName'
|
||||||
else:
|
prop.Value = self.resultFilter
|
||||||
self.doc.storeToURL(self.resultUrl, ())
|
properties.append(prop)
|
||||||
|
if self.resultType == 'csv':
|
||||||
|
# For CSV export, add options (separator, etc)
|
||||||
|
optionsProp = PropertyValue()
|
||||||
|
optionsProp.Name = 'FilterOptions'
|
||||||
|
optionsProp.Value = '59,34,76,1'
|
||||||
|
properties.append(optionsProp)
|
||||||
|
self.doc.storeToURL(self.resultUrl, tuple(properties))
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
'''Connects to OO, does the job and disconnects.'''
|
||||||
self.connect()
|
self.connect()
|
||||||
self.loadDocument()
|
self.loadDocument()
|
||||||
self.convertDocument()
|
self.convertDocument()
|
||||||
self.disconnect()
|
self.doc.close(True)
|
||||||
|
|
||||||
# ConverterScript-related messages ---------------------------------------------
|
# ConverterScript-related messages ---------------------------------------------
|
||||||
WRONG_NB_OF_ARGS = 'Wrong number of arguments.'
|
WRONG_NB_OF_ARGS = 'Wrong number of arguments.'
|
||||||
|
@ -191,12 +242,13 @@ ERROR_CODE = 1
|
||||||
class ConverterScript:
|
class ConverterScript:
|
||||||
usage = 'usage: python converter.py fileToConvert outputType [options]\n' \
|
usage = 'usage: python converter.py fileToConvert outputType [options]\n' \
|
||||||
' where fileToConvert is the absolute or relative pathname of\n' \
|
' where fileToConvert is the absolute or relative pathname of\n' \
|
||||||
' the ODT file you want to convert;\n'\
|
' the file you want to convert (or whose content like\n' \
|
||||||
|
' indexes need to be refreshed);\n'\
|
||||||
' and outputType is the output format, that must be one of\n' \
|
' and outputType is the output format, that must be one of\n' \
|
||||||
' %s.\n' \
|
' %s.\n' \
|
||||||
' "python" should be a UNO-enabled Python interpreter (ie the one\n' \
|
' "python" should be a UNO-enabled Python interpreter (ie the ' \
|
||||||
' which is included in the OpenOffice.org distribution).' % \
|
' one which is included in the OpenOffice.org distribution).' % \
|
||||||
str(ODT_FILE_TYPES.keys())
|
str(FILE_TYPES.keys())
|
||||||
def run(self):
|
def run(self):
|
||||||
optParser = OptionParser(usage=ConverterScript.usage)
|
optParser = OptionParser(usage=ConverterScript.usage)
|
||||||
optParser.add_option("-p", "--port", dest="port",
|
optParser.add_option("-p", "--port", dest="port",
|
||||||
|
|
|
@ -25,7 +25,7 @@ import appy.pod
|
||||||
from appy.pod import PodError
|
from appy.pod import PodError
|
||||||
from appy.shared.xml_parser import XmlElement
|
from appy.shared.xml_parser import XmlElement
|
||||||
from appy.pod.pod_parser import PodParser, PodEnvironment, OdInsert
|
from appy.pod.pod_parser import PodParser, PodEnvironment, OdInsert
|
||||||
from appy.pod.converter import ODT_FILE_TYPES
|
from appy.pod.converter import FILE_TYPES
|
||||||
from appy.pod.buffers import FileBuffer
|
from appy.pod.buffers import FileBuffer
|
||||||
from appy.pod.xhtml2odt import Xhtml2OdtConverter
|
from appy.pod.xhtml2odt import Xhtml2OdtConverter
|
||||||
from appy.pod.doc_importers import OdtImporter, ImageImporter, PdfImporter
|
from appy.pod.doc_importers import OdtImporter, ImageImporter, PdfImporter
|
||||||
|
@ -423,9 +423,9 @@ class Renderer:
|
||||||
os.rename(resultOdtName, self.result)
|
os.rename(resultOdtName, self.result)
|
||||||
else:
|
else:
|
||||||
if resultType.startswith('.'): resultType = resultType[1:]
|
if resultType.startswith('.'): resultType = resultType[1:]
|
||||||
if not resultType in ODT_FILE_TYPES.keys():
|
if not resultType in FILE_TYPES.keys():
|
||||||
raise PodError(BAD_RESULT_TYPE % (
|
raise PodError(BAD_RESULT_TYPE % (
|
||||||
self.result, ODT_FILE_TYPES.keys()))
|
self.result, FILE_TYPES.keys()))
|
||||||
# Call OpenOffice to perform the conversion or document update
|
# Call OpenOffice to perform the conversion or document update
|
||||||
self.callOpenOffice(resultOdtName, resultType)
|
self.callOpenOffice(resultOdtName, resultType)
|
||||||
# I have the result. Move it to the correct name
|
# I have the result. Move it to the correct name
|
||||||
|
|
Loading…
Reference in a new issue